Skip QQ1A.191205.011 in AOSP master

Change-Id: Iaaae882f78fb6718798d5e6429016c2456e4c457
diff --git a/CleanSpec.mk b/CleanSpec.mk
index ebe5f4a..c84bd24 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -80,3 +80,13 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/sbin/charger)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sbin/charger)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/sbin)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/sbin)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/product_services.img)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/product_services)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/debug_ramdisk/product_services)
+$(call add-clean-step, find $(PRODUCT_OUT) -type l -name "charger" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/bin/adbd)
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 716378b..d6945e3 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -4,19 +4,28 @@
       "name": "adbd_test"
     },
     {
+      "name": "CtsInitTestCases"
+    },
+    {
       "name": "debuggerd_test"
     },
     {
-      "name": "fs_mgr_unit_test"
+      "name": "CtsFsMgrTestCases"
     },
     {
       "name": "fs_mgr_vendor_overlay_test"
     },
     {
-      "name": "init_tests"
+      "name": "libbase_test"
     },
     {
-      "name": "libbase_test"
+      "name": "libpackagelistparser_test"
+    },
+    {
+      "name": "libcutils_test"
+    },
+    {
+      "name": "libmodprobe_tests"
     },
     {
       "name": "libprocinfo_test"
@@ -28,6 +37,13 @@
       "name": "memunreachable_test"
     },
     {
+      "name": "memunreachable_unit_test"
+    },
+    {
+      "name": "memunreachable_unit_test",
+      "host": true
+    },
+    {
       "name": "memunreachable_binder_test"
     },
     {
diff --git a/adb/Android.bp b/adb/Android.bp
index 01e00dd..bd1f124 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -26,6 +26,7 @@
         "-Wvla",
         "-DADB_HOST=1",         // overridden by adbd_defaults
         "-DALLOW_ADBD_ROOT=0",  // overridden by adbd_defaults
+        "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION=1",
     ],
     cpp_std: "experimental",
 
@@ -59,6 +60,9 @@
                 // MinGW hides some things behind _POSIX_SOURCE.
                 "-D_POSIX_SOURCE",
 
+                // libusb uses __stdcall on a variadic function, which gets ignored.
+                "-Wno-ignored-attributes",
+
                 // Not supported yet.
                 "-Wno-thread-safety",
             ],
@@ -120,7 +124,8 @@
     "adb_trace.cpp",
     "adb_unique_fd.cpp",
     "adb_utils.cpp",
-    "fdevent.cpp",
+    "fdevent/fdevent.cpp",
+    "fdevent/fdevent_poll.cpp",
     "services.cpp",
     "sockets.cpp",
     "socket_spec.cpp",
@@ -129,6 +134,7 @@
     "transport_fd.cpp",
     "transport_local.cpp",
     "transport_usb.cpp",
+    "types.cpp",
 ]
 
 libadb_posix_srcs = [
@@ -136,11 +142,15 @@
     "sysdeps/posix/network.cpp",
 ]
 
+libadb_linux_srcs = [
+    "fdevent/fdevent_epoll.cpp",
+]
+
 libadb_test_srcs = [
     "adb_io_test.cpp",
     "adb_listeners_test.cpp",
     "adb_utils_test.cpp",
-    "fdevent_test.cpp",
+    "fdevent/fdevent_test.cpp",
     "socket_spec_test.cpp",
     "socket_test.cpp",
     "sysdeps_test.cpp",
@@ -164,12 +174,11 @@
 
     target: {
         linux: {
-            srcs: ["client/usb_linux.cpp"],
+            srcs: ["client/usb_linux.cpp"] + libadb_linux_srcs,
         },
         darwin: {
             srcs: ["client/usb_osx.cpp"],
         },
-
         not_windows: {
             srcs: libadb_posix_srcs,
         },
@@ -216,6 +225,7 @@
     target: {
         windows: {
             enabled: true,
+            ldflags: ["-municode"],
             shared_libs: ["AdbWinApi"],
         },
     },
@@ -243,7 +253,7 @@
         "libbase",
         "libcutils",
         "libcrypto_utils",
-        "libcrypto",
+        "libcrypto_static",
         "libdiagnose_usb",
         "liblog",
         "libusb",
@@ -264,22 +274,33 @@
         "client/console.cpp",
         "client/adb_install.cpp",
         "client/line_printer.cpp",
+        "client/fastdeploy.cpp",
+        "client/fastdeploycallbacks.cpp",
         "shell_service_protocol.cpp",
     ],
 
+    generated_headers: [
+        "bin2c_fastdeployagent",
+        "bin2c_fastdeployagentscript"
+    ],
+
     static_libs: [
         "libadb_host",
+        "libandroidfw",
         "libbase",
         "libcutils",
         "libcrypto_utils",
         "libcrypto",
+        "libfastdeploy_host",
         "libdiagnose_usb",
         "liblog",
         "libmdnssd",
+        "libprotobuf-cpp-lite",
         "libusb",
         "libutils",
         "liblog",
-        "libcutils",
+        "libziparchive",
+        "libz",
     ],
 
     stl: "libc++_static",
@@ -289,10 +310,6 @@
     // will violate ODR
     shared_libs: [],
 
-    required: [
-        "deploypatchgenerator",
-    ],
-
     // Archive adb, adb.exe.
     dist: {
         targets: [
@@ -328,7 +345,7 @@
     // libminadbd wants both, as it's used to build native tests.
     compile_multilib: "both",
 
-    srcs: libadb_srcs + libadb_posix_srcs + [
+    srcs: libadb_srcs + libadb_linux_srcs + libadb_posix_srcs + [
         "daemon/auth.cpp",
         "daemon/jdwp_service.cpp",
     ],
@@ -344,6 +361,8 @@
     ],
 
     shared_libs: [
+        "libadbconnection_server",
+        "libadbd_auth",
         "libasyncio",
         "libbase",
         "libcrypto",
@@ -396,6 +415,8 @@
     ],
 
     shared_libs: [
+        "libadbconnection_server",
+        "libadbd_auth",
         "libasyncio",
         "libbase",
         "libcrypto",
@@ -404,34 +425,16 @@
         "liblog",
     ],
 
-    product_variables: {
-        debuggable: {
-            required: [
-                "remount",
-            ],
-        },
-    },
-
     target: {
         android: {
             srcs: [
                 "daemon/abb_service.cpp",
                 "daemon/framebuffer_service.cpp",
                 "daemon/mdns.cpp",
-                "daemon/reboot_service.cpp",
-                "daemon/remount_service.cpp",
                 "daemon/restart_service.cpp",
-                "daemon/set_verity_enable_state_service.cpp",
-            ],
-            static_libs: [
-                "libavb_user",
             ],
             shared_libs: [
-                "libbootloader_message",
                 "libmdnssd",
-                "libext4_utils",
-                "libfec",
-                "libfs_mgr",
                 "libselinux",
             ],
         },
@@ -460,6 +463,8 @@
     ],
 
     shared_libs: [
+        "libadbconnection_server",
+        "libadbd_auth",
         "libadbd_services",
         "libasyncio",
         "libbase",
@@ -492,17 +497,44 @@
         keep_symbols: true,
     },
 
-    shared_libs: [
+    stl: "libc++_static",
+    static_libs: [
         "libadbd",
+        "libadbd_auth",
         "libadbd_services",
+        "libasyncio",
         "libbase",
         "libcap",
-        "libcrypto",
+        "libcrypto_utils",
         "libcutils",
+        "libdiagnose_usb",
         "liblog",
+        "libmdnssd",
         "libminijail",
         "libselinux",
     ],
+
+    shared_libs: [
+        "libadbconnection_server",
+        "libcrypto",
+    ],
+}
+
+phony {
+    name: "adbd_system_binaries",
+    required: [
+        "abb",
+        "libadbd_auth",
+        "reboot",
+        "set-verity-state",
+    ]
+}
+
+phony {
+    name: "adbd_system_binaries_recovery",
+    required: [
+        "reboot.recovery",
+    ],
 }
 
 cc_binary {
@@ -552,11 +584,11 @@
 
     static_libs: [
         "libadbd",
+        "libadbd_auth",
         "libbase",
-        "libbootloader_message",
         "libcutils",
         "libcrypto_utils",
-        "libcrypto",
+        "libcrypto_static",
         "libdiagnose_usb",
         "liblog",
         "libusb",
@@ -564,6 +596,7 @@
         "libselinux",
     ],
     test_suites: ["device-tests"],
+    require_root: true,
 }
 
 python_test_host {
@@ -604,3 +637,131 @@
         },
     },
 }
+
+// Note: using pipe for xxd to control the variable name generated
+// the default name used by xxd is the path to the input file.
+java_genrule {
+    name: "bin2c_fastdeployagent",
+    out: ["deployagent.inc"],
+    srcs: [":deployagent"],
+    cmd: "(echo 'unsigned char kDeployAgent[] = {' && xxd -i <$(in) && echo '};') > $(out)",
+}
+
+genrule {
+    name: "bin2c_fastdeployagentscript",
+    out: ["deployagentscript.inc"],
+    srcs: ["fastdeploy/deployagent/deployagent.sh"],
+    cmd: "(echo 'unsigned char kDeployAgentScript[] = {' && xxd -i <$(in) && echo '};') > $(out)",
+}
+
+cc_library_host_static {
+    name: "libfastdeploy_host",
+    defaults: ["adb_defaults"],
+    srcs: [
+        "fastdeploy/deploypatchgenerator/apk_archive.cpp",
+        "fastdeploy/deploypatchgenerator/deploy_patch_generator.cpp",
+        "fastdeploy/deploypatchgenerator/patch_utils.cpp",
+        "fastdeploy/proto/ApkEntry.proto",
+    ],
+    static_libs: [
+        "libadb_host",
+        "libandroidfw",
+        "libbase",
+        "libcutils",
+        "libcrypto_utils",
+        "libcrypto",
+        "libdiagnose_usb",
+        "liblog",
+        "libmdnssd",
+        "libusb",
+        "libutils",
+        "libziparchive",
+        "libz",
+    ],
+    stl: "libc++_static",
+    proto: {
+        type: "lite",
+        export_proto_headers: true,
+    },
+    target: {
+        windows: {
+            enabled: true,
+            shared_libs: ["AdbWinApi"],
+        },
+    },
+}
+
+cc_test_host {
+    name: "fastdeploy_test",
+    defaults: ["adb_defaults"],
+    srcs: [
+        "fastdeploy/deploypatchgenerator/apk_archive_test.cpp",
+        "fastdeploy/deploypatchgenerator/deploy_patch_generator_test.cpp",
+        "fastdeploy/deploypatchgenerator/patch_utils_test.cpp",
+    ],
+    static_libs: [
+        "libadb_host",
+        "libandroidfw",
+        "libbase",
+        "libcutils",
+        "libcrypto_utils",
+        "libcrypto",
+        "libdiagnose_usb",
+        "libfastdeploy_host",
+        "liblog",
+        "libmdnssd",
+        "libprotobuf-cpp-lite",
+        "libusb",
+        "libutils",
+        "libziparchive",
+        "libz",
+    ],
+    target: {
+        windows: {
+            enabled: true,
+            shared_libs: ["AdbWinApi"],
+        },
+    },
+    data: [
+        "fastdeploy/testdata/rotating_cube-metadata-release.data",
+        "fastdeploy/testdata/rotating_cube-release.apk",
+        "fastdeploy/testdata/sample.apk",
+        "fastdeploy/testdata/sample.cd",
+    ],
+}
+
+prebuilt_etc {
+    name: "com.android.adbd.ld.config.txt",
+    src: "apex/ld.config.txt",
+    filename: "ld.config.txt",
+    installable: false,
+}
+
+apex {
+    name: "com.android.adbd",
+    manifest: "apex/apex_manifest.json",
+
+    binaries: ["adbd"],
+    prebuilts: ["com.android.adbd.init.rc", "com.android.adbd.ld.config.txt"],
+
+    key: "com.android.adbd.key",
+    certificate: ":com.android.adbd.certificate",
+}
+
+apex_key {
+    name: "com.android.adbd.key",
+    public_key: "apex/com.android.adbd.avbpubkey",
+    private_key: "apex/com.android.adbd.pem",
+}
+
+android_app_certificate {
+    name: "com.android.adbd.certificate",
+    certificate: "apex/com.android.adbd",
+}
+
+prebuilt_etc {
+    name: "com.android.adbd.init.rc",
+    src: "apex/adbd.rc",
+    filename: "init.rc",
+    installable: false,
+}
diff --git a/adb/SOCKET-ACTIVATION.txt b/adb/SOCKET-ACTIVATION.txt
new file mode 100644
index 0000000..4ef62ac
--- /dev/null
+++ b/adb/SOCKET-ACTIVATION.txt
@@ -0,0 +1,42 @@
+adb can be configured to work with systemd-style socket activation,
+allowing the daemon to start automatically when the adb control port
+is forwarded across a network. You need two files, placed in the usual
+systemd service directories (e.g., ~/.config/systemd/user for a user
+service).
+
+adb.service:
+
+--- START adb.service CUT HERE ---
+[Unit]
+Description=adb
+After=adb.socket
+Requires=adb.socket
+[Service]
+Type=simple
+# FD 3 is part of the systemd interface
+ExecStart=/path/to/adb server nodaemon -L acceptfd:3
+--- END adb.service CUT HERE ---
+
+--- START adb.socket CUT HERE ---
+[Unit]
+Description=adb
+PartOf=adb.service
+[Socket]
+ListenStream=127.0.0.1:5037
+Accept=no
+[Install]
+WantedBy=sockets.target
+--- END adb.socket CUT HERE ---
+
+After installing the adb service, the adb server will be started
+automatically on any connection to 127.0.0.1:5037 (the default adb
+control port), even after adb kill-server kills the server.
+
+Other "superserver" launcher systems (like macOS launchd) can be
+configured analogously. The important part is that adb be started with
+"server" and "nodaemon" command line arguments and that the listen
+address (passed to -L) name a file descriptor that's ready to
+accept(2) connections and that's already bound to the desired address
+and listening. inetd-style pre-accepted sockets do _not_ work in this
+configuration: the file descriptor passed to acceptfd must be the
+serve socket, not the accepted connection socket.
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 050ba49..460ddde 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -300,6 +300,7 @@
     handle_online(t);
 #else
     if (!auth_required) {
+        LOG(INFO) << "authentication not required";
         handle_online(t);
         send_connect(t);
     } else {
@@ -1052,9 +1053,9 @@
         // New transport selection protocol:
         // This is essentially identical to the previous version, except it returns the selected
         // transport id to the caller as well.
-        if (ConsumePrefix(&service, "tport:")) {
+        if (android::base::ConsumePrefix(&service, "tport:")) {
             legacy = false;
-            if (ConsumePrefix(&service, "serial:")) {
+            if (android::base::ConsumePrefix(&service, "serial:")) {
                 serial_storage = service;
                 serial = serial_storage.c_str();
             } else if (service == "usb") {
@@ -1068,7 +1069,7 @@
             // Selection by id is unimplemented, since you obviously already know the transport id
             // you're connecting to.
         } else {
-            if (ConsumePrefix(&service, "transport-id:")) {
+            if (android::base::ConsumePrefix(&service, "transport-id:")) {
                 if (!ParseUint(&transport_id, service)) {
                     SendFail(reply_fd, "invalid transport id");
                     return HostRequestResult::Handled;
@@ -1079,7 +1080,7 @@
                 type = kTransportLocal;
             } else if (service == "transport-any") {
                 type = kTransportAny;
-            } else if (ConsumePrefix(&service, "transport:")) {
+            } else if (android::base::ConsumePrefix(&service, "transport:")) {
                 serial_storage = service;
                 serial = serial_storage.c_str();
             }
@@ -1131,7 +1132,9 @@
 
     if (service == "features") {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
+        atransport* t =
+                s->transport ? s->transport
+                             : acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t != nullptr) {
             SendOkay(reply_fd, FeatureSetToString(t->features()));
         } else {
@@ -1164,7 +1167,7 @@
         std::string host;
         int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
         std::string error;
-        if (address.starts_with("vsock:")) {
+        if (address.starts_with("vsock:") || address.starts_with("localfilesystem:")) {
             serial = address;
         } else if (!android::base::ParseNetAddress(address, &host, &port, &serial, &error)) {
             SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
@@ -1190,7 +1193,9 @@
     // These always report "unknown" rather than the actual error, for scripts.
     if (service == "get-serialno") {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
+        atransport* t =
+                s->transport ? s->transport
+                             : acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
             SendOkay(reply_fd, !t->serial.empty() ? t->serial : "unknown");
         } else {
@@ -1200,7 +1205,9 @@
     }
     if (service == "get-devpath") {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
+        atransport* t =
+                s->transport ? s->transport
+                             : acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
             SendOkay(reply_fd, !t->devpath.empty() ? t->devpath : "unknown");
         } else {
@@ -1210,7 +1217,9 @@
     }
     if (service == "get-state") {
         std::string error;
-        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &error);
+        atransport* t =
+                s->transport ? s->transport
+                             : acquire_one_transport(type, serial, transport_id, nullptr, &error);
         if (t) {
             SendOkay(reply_fd, t->connection_state_name());
         } else {
@@ -1220,7 +1229,7 @@
     }
 
     // Indicates a new emulator instance has started.
-    if (ConsumePrefix(&service, "emulator:")) {
+    if (android::base::ConsumePrefix(&service, "emulator:")) {
         unsigned int port;
         if (!ParseUint(&port, service)) {
           LOG(ERROR) << "received invalid port for emulator: " << service;
@@ -1234,7 +1243,9 @@
 
     if (service == "reconnect") {
         std::string response;
-        atransport* t = acquire_one_transport(type, serial, transport_id, nullptr, &response, true);
+        atransport* t = s->transport ? s->transport
+                                     : acquire_one_transport(type, serial, transport_id, nullptr,
+                                                             &response, true);
         if (t != nullptr) {
             kick_transport(t, true);
             response =
@@ -1246,12 +1257,15 @@
 
     // TODO: Switch handle_forward_request to string_view.
     std::string service_str(service);
-    if (handle_forward_request(
-                service_str.c_str(),
-                [=](std::string* error) {
-                    return acquire_one_transport(type, serial, transport_id, nullptr, error);
-                },
-                reply_fd)) {
+    auto transport_acquirer = [=](std::string* error) {
+        if (s->transport) {
+            return s->transport;
+        } else {
+            std::string error;
+            return acquire_one_transport(type, serial, transport_id, nullptr, &error);
+        }
+    };
+    if (handle_forward_request(service_str.c_str(), transport_acquirer, reply_fd)) {
         return HostRequestResult::Handled;
     }
 
diff --git a/adb/adb.h b/adb/adb.h
index 9324cee..e7fcc91 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -26,7 +26,7 @@
 #include <android-base/macros.h>
 
 #include "adb_trace.h"
-#include "fdevent.h"
+#include "fdevent/fdevent.h"
 #include "socket.h"
 #include "types.h"
 #include "usb.h"
@@ -200,7 +200,7 @@
 #define ADB_SUBCLASS 0x42
 #define ADB_PROTOCOL 0x1
 
-void local_init(int port);
+void local_init(const std::string& addr);
 bool local_connect(int port);
 int local_connect_arbitrary_ports(int console_port, int adb_port, std::string* error);
 
diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp
index f5cdcb5..bdb8efa 100644
--- a/adb/adb_io.cpp
+++ b/adb/adb_io.cpp
@@ -34,7 +34,7 @@
 #include "adb_utils.h"
 #include "sysdeps.h"
 
-bool SendProtocolString(int fd, std::string_view s) {
+bool SendProtocolString(borrowed_fd fd, std::string_view s) {
     unsigned int length = s.size();
     if (length > MAX_PAYLOAD - 4) {
         errno = EMSGSIZE;
@@ -47,7 +47,7 @@
     return WriteFdExactly(fd, str);
 }
 
-bool ReadProtocolString(int fd, std::string* s, std::string* error) {
+bool ReadProtocolString(borrowed_fd fd, std::string* s, std::string* error) {
     char buf[5];
     if (!ReadFdExactly(fd, buf, 4)) {
         *error = perror_str("protocol fault (couldn't read status length)");
@@ -65,57 +65,57 @@
     return true;
 }
 
-bool SendOkay(int fd) {
+bool SendOkay(borrowed_fd fd) {
     return WriteFdExactly(fd, "OKAY", 4);
 }
 
-bool SendFail(int fd, std::string_view reason) {
+bool SendFail(borrowed_fd fd, std::string_view reason) {
     return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason);
 }
 
-bool ReadFdExactly(int fd, void* buf, size_t len) {
+bool ReadFdExactly(borrowed_fd fd, void* buf, size_t len) {
     char* p = reinterpret_cast<char*>(buf);
 
     size_t len0 = len;
 
-    D("readx: fd=%d wanted=%zu", fd, len);
+    D("readx: fd=%d wanted=%zu", fd.get(), len);
     while (len > 0) {
         int r = adb_read(fd, p, len);
         if (r > 0) {
             len -= r;
             p += r;
         } else if (r == -1) {
-            D("readx: fd=%d error %d: %s", fd, errno, strerror(errno));
+            D("readx: fd=%d error %d: %s", fd.get(), errno, strerror(errno));
             return false;
         } else {
-            D("readx: fd=%d disconnected", fd);
+            D("readx: fd=%d disconnected", fd.get());
             errno = 0;
             return false;
         }
     }
 
-    VLOG(RWX) << "readx: fd=" << fd << " wanted=" << len0 << " got=" << (len0 - len)
-              << " " << dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
+    VLOG(RWX) << "readx: fd=" << fd.get() << " wanted=" << len0 << " got=" << (len0 - len) << " "
+              << dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
 
     return true;
 }
 
-bool WriteFdExactly(int fd, const void* buf, size_t len) {
+bool WriteFdExactly(borrowed_fd fd, const void* buf, size_t len) {
     const char* p = reinterpret_cast<const char*>(buf);
     int r;
 
-    VLOG(RWX) << "writex: fd=" << fd << " len=" << len
-              << " " << dump_hex(reinterpret_cast<const unsigned char*>(buf), len);
+    VLOG(RWX) << "writex: fd=" << fd.get() << " len=" << len << " "
+              << dump_hex(reinterpret_cast<const unsigned char*>(buf), len);
 
     while (len > 0) {
         r = adb_write(fd, p, len);
         if (r == -1) {
-            D("writex: fd=%d error %d: %s", fd, errno, strerror(errno));
+            D("writex: fd=%d error %d: %s", fd.get(), errno, strerror(errno));
             if (errno == EAGAIN) {
                 std::this_thread::yield();
                 continue;
             } else if (errno == EPIPE) {
-                D("writex: fd=%d disconnected", fd);
+                D("writex: fd=%d disconnected", fd.get());
                 errno = 0;
                 return false;
             } else {
@@ -129,15 +129,15 @@
     return true;
 }
 
-bool WriteFdExactly(int fd, const char* str) {
+bool WriteFdExactly(borrowed_fd fd, const char* str) {
     return WriteFdExactly(fd, str, strlen(str));
 }
 
-bool WriteFdExactly(int fd, const std::string& str) {
+bool WriteFdExactly(borrowed_fd fd, const std::string& str) {
     return WriteFdExactly(fd, str.c_str(), str.size());
 }
 
-bool WriteFdFmt(int fd, const char* fmt, ...) {
+bool WriteFdFmt(borrowed_fd fd, const char* fmt, ...) {
     std::string str;
 
     va_list ap;
@@ -148,7 +148,7 @@
     return WriteFdExactly(fd, str);
 }
 
-bool ReadOrderlyShutdown(int fd) {
+bool ReadOrderlyShutdown(borrowed_fd fd) {
     char buf[16];
 
     // Only call this function if you're sure that the peer does
@@ -178,7 +178,7 @@
         // data. We don't repeatedly call adb_read() until we get zero because
         // we don't know how long that would take, but we do know that the
         // caller wants to close the socket soon.
-        VLOG(RWX) << "ReadOrderlyShutdown(" << fd << ") unexpectedly read "
+        VLOG(RWX) << "ReadOrderlyShutdown(" << fd.get() << ") unexpectedly read "
                   << dump_hex(buf, result);
         // Shutdown the socket to prevent the caller from reading or writing to
         // it which doesn't make sense if we just read and discarded some data.
diff --git a/adb/adb_io.h b/adb/adb_io.h
index d6e65d8..9628946 100644
--- a/adb/adb_io.h
+++ b/adb/adb_io.h
@@ -25,16 +25,16 @@
 #include "adb_unique_fd.h"
 
 // Sends the protocol "OKAY" message.
-bool SendOkay(int fd);
+bool SendOkay(borrowed_fd fd);
 
 // Sends the protocol "FAIL" message, with the given failure reason.
-bool SendFail(int fd, std::string_view reason);
+bool SendFail(borrowed_fd fd, std::string_view reason);
 
 // Writes a protocol-format string; a four hex digit length followed by the string data.
-bool SendProtocolString(int fd, std::string_view s);
+bool SendProtocolString(borrowed_fd fd, std::string_view s);
 
 // Reads a protocol-format string; a four hex digit length followed by the string data.
-bool ReadProtocolString(int fd, std::string* s, std::string* error);
+bool ReadProtocolString(borrowed_fd fd, std::string* s, std::string* error);
 
 // Reads exactly len bytes from fd into buf.
 //
@@ -42,7 +42,7 @@
 // were read. If EOF was found, errno will be set to 0.
 //
 // If this function fails, the contents of buf are undefined.
-bool ReadFdExactly(int fd, void* buf, size_t len);
+bool ReadFdExactly(borrowed_fd fd, void* buf, size_t len);
 
 // Given a client socket, wait for orderly/graceful shutdown. Call this:
 //
@@ -60,19 +60,19 @@
 // connect()s from the client to fail with WSAEADDRINUSE on Windows.
 // Returns true if it is sure that orderly/graceful shutdown has occurred with
 // no additional data read from the server.
-bool ReadOrderlyShutdown(int fd);
+bool ReadOrderlyShutdown(borrowed_fd fd);
 
 // Writes exactly len bytes from buf to fd.
 //
 // Returns false if there is an error or if the fd was closed before the write
 // completed. If the other end of the fd (such as in a socket, pipe, or fifo),
 // is closed, errno will be set to 0.
-bool WriteFdExactly(int fd, const void* buf, size_t len);
+bool WriteFdExactly(borrowed_fd fd, const void* buf, size_t len);
 
 // Same as above, but for strings.
-bool WriteFdExactly(int fd, const char* s);
-bool WriteFdExactly(int fd, const std::string& s);
+bool WriteFdExactly(borrowed_fd fd, const char* s);
+bool WriteFdExactly(borrowed_fd fd, const std::string& s);
 
 // Same as above, but formats the string to send.
-bool WriteFdFmt(int fd, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
+bool WriteFdFmt(borrowed_fd fd, const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
 #endif /* ADB_IO_H */
diff --git a/adb/adb_listeners_test.cpp b/adb/adb_listeners_test.cpp
index b697769..a7e2dea 100644
--- a/adb/adb_listeners_test.cpp
+++ b/adb/adb_listeners_test.cpp
@@ -21,7 +21,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
-#include "fdevent.h"
+#include "fdevent/fdevent.h"
 #include "sysdeps.h"
 #include "transport.h"
 
diff --git a/adb/adb_unique_fd.h b/adb/adb_unique_fd.h
index d47213d..b6c910a 100644
--- a/adb/adb_unique_fd.h
+++ b/adb/adb_unique_fd.h
@@ -32,6 +32,8 @@
 using unique_fd = android::base::unique_fd;
 #endif
 
+using android::base::borrowed_fd;
+
 template <typename T>
 int adb_close(const android::base::unique_fd_impl<T>&)
         __attribute__((__unavailable__("adb_close called on unique_fd")));
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 9791769..d1910f1 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -234,15 +234,15 @@
 
 #if !defined(_WIN32)
 // Windows version provided in sysdeps_win32.cpp
-bool set_file_block_mode(int fd, bool block) {
-    int flags = fcntl(fd, F_GETFL, 0);
+bool set_file_block_mode(borrowed_fd fd, bool block) {
+    int flags = fcntl(fd.get(), F_GETFL, 0);
     if (flags == -1) {
-        PLOG(ERROR) << "failed to fcntl(F_GETFL) for fd " << fd;
+        PLOG(ERROR) << "failed to fcntl(F_GETFL) for fd " << fd.get();
         return false;
     }
     flags = block ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
-    if (fcntl(fd, F_SETFL, flags) != 0) {
-        PLOG(ERROR) << "failed to fcntl(F_SETFL) for fd " << fd << ", flags " << flags;
+    if (fcntl(fd.get(), F_SETFL, flags) != 0) {
+        PLOG(ERROR) << "failed to fcntl(F_SETFL) for fd " << fd.get() << ", flags " << flags;
         return false;
     }
     return true;
@@ -320,6 +320,10 @@
 }
 
 std::string GetLogFilePath() {
+    // https://issuetracker.google.com/112588493
+    const char* path = getenv("ANDROID_ADB_LOG_PATH");
+    if (path) return path;
+
 #if defined(_WIN32)
     const char log_name[] = "adb.log";
     WCHAR temp_path[MAX_PATH];
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 5800a62..66cba12 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <charconv>
 #include <condition_variable>
 #include <mutex>
 #include <string>
@@ -26,6 +27,7 @@
 #include <android-base/macros.h>
 
 #include "adb.h"
+#include "adb_unique_fd.h"
 
 void close_stdin();
 
@@ -51,7 +53,7 @@
 [[noreturn]] void error_exit(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
 [[noreturn]] void perror_exit(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
 
-bool set_file_block_mode(int fd, bool block);
+bool set_file_block_mode(borrowed_fd fd, bool block);
 
 // Given forward/reverse targets, returns true if they look sane. If an error is found, fills
 // |error| and returns false.
@@ -111,41 +113,17 @@
 // Base-10 stroll on a string_view.
 template <typename T>
 inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining = nullptr) {
-    if (str.empty() || !isdigit(str[0])) {
+    T value;
+    const auto res = std::from_chars(str.begin(), str.end(), value);
+    if (res.ec != std::errc{}) {
         return false;
     }
-
-    T value = 0;
-    std::string_view::iterator it;
-    constexpr T max = std::numeric_limits<T>::max();
-    for (it = str.begin(); it != str.end() && isdigit(*it); ++it) {
-        if (value > max / 10) {
-            return false;
-        }
-
-        value *= 10;
-
-        T digit = *it - '0';
-        if (value > max - digit) {
-            return false;
-        }
-
-        value += digit;
+    if (res.ptr != str.end() && !remaining) {
+        return false;
+    }
+    if (remaining) {
+        *remaining = std::string_view(res.ptr, str.end() - res.ptr);
     }
     *result = value;
-    if (remaining) {
-        *remaining = str.substr(it - str.begin());
-    } else {
-      return it == str.end();
-    }
-
     return true;
 }
-
-inline bool ConsumePrefix(std::string_view* str, std::string_view prefix) {
-  if (str->starts_with(prefix)) {
-    str->remove_prefix(prefix.size());
-    return true;
-  }
-  return false;
-}
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index bd676c2..cdca3aa 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -149,13 +149,13 @@
 TEST(adb_utils, set_file_block_mode) {
     unique_fd fd(adb_open("/dev/null", O_RDWR | O_APPEND));
     ASSERT_GE(fd, 0);
-    int flags = fcntl(fd, F_GETFL, 0);
+    int flags = fcntl(fd.get(), F_GETFL, 0);
     ASSERT_EQ(O_RDWR | O_APPEND, (flags & (O_RDWR | O_APPEND)));
     ASSERT_TRUE(set_file_block_mode(fd, false));
-    int new_flags = fcntl(fd, F_GETFL, 0);
+    int new_flags = fcntl(fd.get(), F_GETFL, 0);
     ASSERT_EQ(flags | O_NONBLOCK, new_flags);
     ASSERT_TRUE(set_file_block_mode(fd, true));
-    new_flags = fcntl(fd, F_GETFL, 0);
+    new_flags = fcntl(fd.get(), F_GETFL, 0);
     ASSERT_EQ(flags, new_flags);
 }
 #endif
diff --git a/adb/apex/adbd.rc b/adb/apex/adbd.rc
new file mode 100644
index 0000000..9cb072b
--- /dev/null
+++ b/adb/apex/adbd.rc
@@ -0,0 +1,6 @@
+service adbd /apex/com.android.adbd/bin/adbd --root_seclabel=u:r:su:s0
+    class core
+    socket adbd seqpacket 660 system system
+    disabled
+    override
+    seclabel u:r:adbd:s0
diff --git a/adb/apex/apex_manifest.json b/adb/apex/apex_manifest.json
new file mode 100644
index 0000000..ff2df12
--- /dev/null
+++ b/adb/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.adbd",
+  "version": 1
+}
diff --git a/adb/apex/com.android.adbd.avbpubkey b/adb/apex/com.android.adbd.avbpubkey
new file mode 100644
index 0000000..06235bd
--- /dev/null
+++ b/adb/apex/com.android.adbd.avbpubkey
Binary files differ
diff --git a/adb/apex/com.android.adbd.pem b/adb/apex/com.android.adbd.pem
new file mode 100644
index 0000000..2c9a860
--- /dev/null
+++ b/adb/apex/com.android.adbd.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAwUmO4l/ZdLhmBcBtpwDjih6z6bC7iZDPAVgnFVnYuYDRlVDA
+9OCDwv02Wwc/YCNzON7vt7JBk3o9wyJZpqY9HR1PUjk2DJa/wHtxbskmLcqsvcoh
+wZxmMkgx1mFyni/vQ0tCjjxYmDcnpoVmSntoPG4LBTZRwbgE2roYSuEi7q88Z9+t
+cFiQ5x7MqVTzUFsi1E+rpsxRaTt6Ly9DO71yR1gMTqONsSgmFm8f2HhUCiQzRh7H
+qLwk8eN5ZLPLVc1JBqo8swuH5pR9whR8HaYyQtK1VANRR9oVj3JpRXmyFUk8QjEn
+91I3sFV1lErdP1uh6xi6ewMBp+mQ+ccNFiNJs8PHVprzbEgX2ah45Tnge95ZwnkR
+V/5G/EwGBsggk/BcZjQyj0PExG6LmygR7lq8q4m9ODJj3cmNLZsZu8ukMBxf4Fim
+4/Y7lyaelW0FL+x3CR27wlIxLyIf/JfUNv/cFO/O2MHrDHYdHtCbvg8vpq1MZtDN
++gJIkYQNUfBEtGS4SkH3WWfNet3bcL5yFx5IVdwCY+n635jPA1fvr1vcIiKnyGUm
+zNE+jMOZkgk6lPPuDwllAX0D8nYTm1eBMCTAWCePO0QlcFHCT9j1/xKbFbjt/xYI
+0pXuOc8/1n61F5ybzH/91cS66gqmYUAekUiP0osTIZ7idVFJMoqpc9m7+rECAwEA
+AQKCAgEAkjg9WU89SCk/NNavnQj1GUXEwOKr3JOppdC0MFi5tQuYgSaH8jfuNZIs
+joxbCzWGMt2j5wl4xkJRes7/lyxnSyEjIoaZNsjL4qb/1tlggn+yUhkZlEfmn98x
+pIYvmS+WBwhmHwfT1cLTwgtkqK/W2PA+cgD3tF6rfXQOcIcEUCBMyB/UKws1A0Kv
+fOIA9ycaoBZtOk+SvtL5ybwtVoIoc4ROOydLR1uiBJKoOrA8kzdzenZKgIFkSYDW
+ErJY/l3AAsTCCoiMlIh84ldw1VUm7JpOBnJECOEYMl5Q+PfpGmU+qqxZGaYe7syX
+mElSOl3tjdY1LF3H4Oi2fd5xLfAgDgQjXcawKRYpImEgbqNfEUHW4BE/uVp0hHn+
+W0tCq9hvWoizhjxVq7oEfpdCXJBH0bTg9h3Ho2nuJMHTrUVbSWPTqNJn1xOi4Oxl
+vWsD5qjOOVw1e0P1dtxQ+6a8+rCL8LDvIthQC9Wpt0yXduEi/vUWiMFx2VbcSpNn
+5PB9HK7vvCpR/k0IocaTKt80D3m2svJCnfrekRx/7n//x8imrvtvaYNpoToTSN0q
+hPOpTNc77R4aARJNXm4sVHzGs6HUXsJfODJdjFtTuaDHjLvRoXZi2wFUVWBvIaFg
+/4+PHXjsfMkY15KULKn3f7Xs7K6rmINAb853zti3Qkllv1EeYoECggEBAP9t1Jxe
+hLKnVrJ5jJ0zCT0/ez6qM5cQG8YvXbVICmoAOQ+/NV6qjPABg5j8FuNhpyr45OuJ
+m1oISLgZPVCbIvYx3oZS4ekWUp9Z7jlDGzsWiBCkEUFLRzDLQRUl4bQMI2SWM+vD
+RL9AAM+NHJQ8LJN7ASNdSQw9ZinNCSByCZ52QjPCfRON0OPY4l1FJKHHymzBNXpe
+R5e9a1o9KEIhd7j+3YX9y8SOVrbUe6U8me5LZ6RY+pLB+cA/UHcSQK23hYAkMcvL
+MQny6B57P6rquzFZDG/OUOZWzWub2FSYTTmiYSHPAuB15FyWShs7h7+wK8y2xrSM
+Lq3FWHxzR1OK2HkCggEBAMG4KsAU/lp9rQhNpdw2NQXqbDLgHy09BFMOOWhyp2/Z
+2lbDo9aP746Q56HAfRRgx5oAAtr3SxeN/R/uEJLYzzDU+SrG4TQO/TZ3DPZOAVYM
+oESWG/HXLN4Hw6j4iWt2NvqpnSVJrvYr6zar/QxRHOMwnUoUV3ugmzUkqFC/Nwmm
+nMGJbTQbEha8OyatfwejmhrCkbQMBiCk0AQmgLybUxs2ckGs5jibau7VqXVxly0f
+WkAsWE/qfybQl4oyBhGCFNObr3Co/PHTaD4ACFQQvaEEF4bTuh6wP+MIgJKxL8IB
+SkrKWO5PFbJWY5lacnNMe7ITrWy60HukLlJe5or5lfkCggEBAP3Rwghw1CRDrR9F
+Mbm0UWYPgwTOVN20ICVcRB40LEURW6KOOxaLG+oTVxXay1PAYkGNes2jvEBHIxvt
+2MQUpTVIcPvBuMPKbufykYtNZ+3bgfInVw4vI9sU3uOI9TPZLAJ0T7vkGpiBnUyh
+yNh0w0b6YDMoK8KB8Ndw67TWHUDd+wM8LNYVgpInnylX4ALzae+QPvgOX84laFwP
+kcXFRBcNDExt2uLDHuAnXYbhJYVqYN8rnDPhlbC4OdlYxfTZ/UtMrD769wwP2SER
+ED9jagirmHQx7Ko3b4GTJ/FINtUiyqqx7wXloLtwjMtq6IZPJfcTWXloI6qCBGAG
+ncYinuECggEAfZeiF8BEm3RpTz3QL3HxdHFkTqOhctnhSNuq+n2C8nBCLwhN21ic
+DkkB84txTFnmboBdWYsEYzQKDL5yflIUGeup00L3VKH3Jm2OuM0f7qLm8TCE04kW
+rKhKAO2JYmNVB7QZjsgzp6QXre1ZdLfNy7mD8Dg584vPtGecvCUMULR1YsBvTV3T
+n2vPyaan+dLmoTzN6/XzrwxLVLWFt0HYYoctEkk/RSn17PwXDm5jfbya7YoSg1Vb
+tFV+Oflul8FHMV35I0hcHYhbR/8LZz0nRBH8EsyIGUdZVB76BKDdfqEJgm2ntHEP
+dvytPAo4s2m9tFkvkZOYgOCTq5GdVDK2OQKCAQAsz+y9rDcqFciCESu4IHzmtckT
+0kwP2W5ds5hzUjbY0Y2AKTx2oHNOFak6WW5vxN0+OIn37SNK3RBStPWJiigut4R4
+rGrZM4pijm53s3cWzd0h8XyLGisl2zORu8gD2IQLkQf79F3lEZHGA+J0mkSHB85N
+IuqReFzL6cfOToNd+8WYjMgJcXmVuKiCV1FRK3jrqNpXO2cLtnhFvQMxRUAYU4j+
+2MIdBFVeMq5ftMMOBS21hM9cNLlOzoSN2HmK+ZkmrlTCK0G9lmF427/lqXTmWLed
+sspOUbOLfBOwxdCCc9JUxz5KggKWcDcTqX25M0mv09rpuCxIEg8lez1Ax0if
+-----END RSA PRIVATE KEY-----
diff --git a/adb/apex/com.android.adbd.pk8 b/adb/apex/com.android.adbd.pk8
new file mode 100644
index 0000000..cdddc3f
--- /dev/null
+++ b/adb/apex/com.android.adbd.pk8
Binary files differ
diff --git a/adb/apex/com.android.adbd.x509.pem b/adb/apex/com.android.adbd.x509.pem
new file mode 100644
index 0000000..bb85c1d
--- /dev/null
+++ b/adb/apex/com.android.adbd.x509.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGHzCCBAegAwIBAgIUW8npFHXBP+wsEAesGMBxaV7TScAwDQYJKoZIhvcNAQEL
+BQAwgZ0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMRkwFwYDVQQDDBBjb20uYW5kcm9pZC5hZGJkMSIwIAYJKoZIhvcNAQkBFhNh
+bmRyb2lkQGFuZHJvaWQuY29tMCAXDTE5MDgxNTE5MzkxM1oYDzQ3NTcwNzExMTkz
+OTEzWjCBnTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNV
+BAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB0FuZHJvaWQxEDAOBgNVBAsMB0Fu
+ZHJvaWQxGTAXBgNVBAMMEGNvbS5hbmRyb2lkLmFkYmQxIjAgBgkqhkiG9w0BCQEW
+E2FuZHJvaWRAYW5kcm9pZC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQC6zbUeWi5vNA6vCC4FBrJQ9re4UexP6TabsDYvWpFBoCluvMkT2ZRmpXMF
+W7EzQ5VmuUvZgLYVHuJmnvHIV3uaRc2VE1SV+spjWTRt+6DtsAN7irR5K66POWMp
++tr5hASdQBVOJdebimsepy0pH6sXREvanrrFzkSM/2Ho0unlwWJ5Y4jcnvdkVHI5
+Ks0vifLmX4y5mYgv1dcXYWzyYx39f8HyePv0cjRhYXiIEYZ49KWU4MjryvQe/mAu
+MQuMp901BLps2W1+oKyPPA4DV69KUXgF66RFfsjjkJJ/CSeQGzTuez+UWzFk3Duc
+6MmbiL1LTki3vyyVtjW1rYFO2s+M6Pa5NZWHgA55uUxiJ987WPyK9lWnMsY6YeKa
+FDBfS1JUzXGPzVncgM7LLvzAEibLdhjII88NsJvzPoHK0SluSn+E7t7iGO1fTjkD
+Js94iUJAp8OQ4GwkcTVgtEAR+NXzownNjHJ6qpiq6tXRqXdBqSat/glf01AgNDtz
+9AGeW7Mz6FqTdOzg3U4lu77+CGd3SZTuQk8C8PUDNhqhQX5H2qhr90bakGaXuYfE
+rWFzIjrVdJIznV1BimOCay5HyyHab4FWlVhAvslEQb2BpHRyi2lhe0laupOpmN44
+LzfjFM18bi2GashIi2OQuYDyAeT5mGtR2g8mC7g44H6dH+wTfQIDAQABo1MwUTAd
+BgNVHQ4EFgQU7lyyxPO5SOOh9a5O0l4+RjckcgcwHwYDVR0jBBgwFoAU7lyyxPO5
+SOOh9a5O0l4+RjckcgcwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AgEAStsOy8bkbZg/Ygx47bPkLSz0cJIvATxTChUGOabkz+brLis88ABVWVP0IXps
+tlLlZR5cjXBJguE7GJXzKPWzQZuB8+YwcGHG6QDFpfdMeGrxPDhwNfGy236ArVnx
+K0v1IIxoZRZ0P7aubk3xwUAPgsmT5ayZCKu+dqlEy5B6ioKEsr7Y2RRT/8ifERNm
+cjS9AhcyWrp4R3cjy2iA/RpdsPFwE5ac3I+GtUB4D2up5aDMsy85i9t2/1kuTUaA
+9UHwGXCpcqP8f8BqeLzuxDzYkAvkntlNxbXn1cbn+dTRIOCBoDbtSeqtxhWooOUH
+RQROeRsB7iicdYJJRge0+WyR+216AKUSQPE6/rT0Ifr06ZRwi22/YyySpwuO3SNA
++yWffh+f4h31Dz+p6pu8wjbMDkq4LnCWyjLwfF/yhvWhwwm5+KPAEhvJABeHQc+3
+cslOC9dlXJm9sPoUC7ghmUiFsCmN2hIzQrr2QoK0Obh0AGexOvOAw9cqtOdZQncB
+bqC8c4sVYScVxwDWkg0lNfRMC5boPjBsl7+M2CC1ukgVpXTyDOEjMWILrBXfYCDX
+unBH3kbKQOfL5RT0nE1Lkt1rn5qAWMJg4mvS4QuIurbRtEoj3QYQadF9md4qJXs0
+TvqvY8iEC4xrWU2SQn1K3PutXgaLP9/b6Cy1SBrhBX+AC5s=
+-----END CERTIFICATE-----
diff --git a/adb/apex/ld.config.txt b/adb/apex/ld.config.txt
new file mode 100644
index 0000000..85f9b29
--- /dev/null
+++ b/adb/apex/ld.config.txt
@@ -0,0 +1,51 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Bionic loader config file for the adbd APEX.
+
+dir.adbd = /apex/com.android.adbd/bin/
+
+[adbd]
+additional.namespaces = platform,art,adbd
+
+namespace.default.isolated = true
+namespace.default.links = art,adbd,platform
+namespace.default.link.art.shared_libs = libadbconnection_server.so
+namespace.default.link.platform.allow_all_shared_libs = true
+namespace.default.link.adbd.allow_all_shared_libs = true
+
+###############################################################################
+# "adbd" APEX namespace
+###############################################################################
+namespace.adbd.isolated = true
+namespace.adbd.search.paths = /apex/com.android.adbd/${LIB}
+namespace.adbd.asan.search.paths = /apex/com.android.adbd/${LIB}
+namespace.adbd.links = platform
+namespace.adbd.link.platform.allow_all_shared_libs = true
+
+###############################################################################
+# "art" APEX namespace: used for libadbdconnection_server
+###############################################################################
+namespace.art.isolated = true
+namespace.art.search.paths = /apex/com.android.art/${LIB}
+namespace.art.asan.search.paths = /apex/com.android.art/${LIB}
+namespace.art.links = platform
+namespace.art.link.platform.allow_all_shared_libs = true
+
+###############################################################################
+# "platform" namespace: used for NDK libraries, and libadbd_auth
+###############################################################################
+namespace.platform.isolated = true
+namespace.platform.search.paths = /system/${LIB}
+namespace.platform.asan.search.paths = /data/asan/system/${LIB}
+
+# /system/lib/libc.so, etc are symlinks to
+# /apex/com.android.runtime/lib/bionic/libc.so, etc. Add the path to the
+# permitted paths because linker uses realpath(3) to check the accessibility
+# of the lib. We could add this to search.paths instead but that makes the
+# resolution of bionic libs be dependent on the order of /system/lib and
+# /apex/.../lib/bionic in search.paths. If the latter is after the former,
+# then the latter is never tried because libc.so is always found in
+# /system/lib but fails to pass the accessibility test because of its realpath.
+# It's better to not depend on the ordering if possible.
+namespace.platform.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
+namespace.platform.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
diff --git a/adb/client/adb_client.cpp b/adb/client/adb_client.cpp
index 5a7bc8d..f724cb5 100644
--- a/adb/client/adb_client.cpp
+++ b/adb/client/adb_client.cpp
@@ -128,7 +128,7 @@
     return result;
 }
 
-bool adb_status(int fd, std::string* error) {
+bool adb_status(borrowed_fd fd, std::string* error) {
     char buf[5];
     if (!ReadFdExactly(fd, buf, 4)) {
         *error = perror_str("protocol fault (couldn't read status)");
@@ -149,7 +149,8 @@
     return false;
 }
 
-static int _adb_connect(std::string_view service, TransportId* transport, std::string* error) {
+static int _adb_connect(std::string_view service, TransportId* transport, std::string* error,
+                        bool force_switch = false) {
     LOG(DEBUG) << "_adb_connect: " << service;
     if (service.empty() || service.size() > MAX_PAYLOAD) {
         *error = android::base::StringPrintf("bad service name length (%zd)", service.size());
@@ -164,7 +165,7 @@
         return -2;
     }
 
-    if (!service.starts_with("host")) {
+    if (!service.starts_with("host") || force_switch) {
         std::optional<TransportId> transport_result = switch_socket_transport(fd.get(), error);
         if (!transport_result) {
             return -1;
@@ -221,7 +222,7 @@
     int port;
     std::string error;
     if (!parse_tcp_socket_spec(__adb_server_socket_spec, nullptr, &port, nullptr, &error)) {
-        LOG(FATAL) << "failed to parse server socket spec: " << error;
+        return {};
     }
 
     return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adb." + std::to_string(port);
@@ -323,7 +324,8 @@
     return result;
 }
 
-int adb_connect(TransportId* transport, std::string_view service, std::string* error) {
+int adb_connect(TransportId* transport, std::string_view service, std::string* error,
+                bool force_switch_device) {
     LOG(DEBUG) << "adb_connect: service: " << service;
 
     // Query the adb server's version.
@@ -336,7 +338,7 @@
         return 0;
     }
 
-    unique_fd fd(_adb_connect(service, transport, error));
+    unique_fd fd(_adb_connect(service, transport, error, force_switch_device));
     if (fd == -1) {
         D("_adb_connect error: %s", error->c_str());
     } else if(fd == -2) {
@@ -398,9 +400,15 @@
 }
 
 bool adb_get_feature_set(FeatureSet* feature_set, std::string* error) {
-    std::string result;
-    if (adb_query(format_host_command("features"), &result, error)) {
-        *feature_set = StringToFeatureSet(result);
+    static FeatureSet* features = nullptr;
+    if (!features) {
+        std::string result;
+        if (adb_query(format_host_command("features"), &result, error)) {
+            features = new FeatureSet(StringToFeatureSet(result));
+        }
+    }
+    if (features) {
+        *feature_set = *features;
         return true;
     }
     feature_set->clear();
diff --git a/adb/client/adb_client.h b/adb/client/adb_client.h
index 8d32c93..ba53041 100644
--- a/adb/client/adb_client.h
+++ b/adb/client/adb_client.h
@@ -16,13 +16,14 @@
 
 #pragma once
 
-#include "adb.h"
-#include "sysdeps.h"
-#include "transport.h"
-
 #include <optional>
 #include <string>
 
+#include "adb.h"
+#include "adb_unique_fd.h"
+#include "sysdeps.h"
+#include "transport.h"
+
 // Explicitly check the adb server version.
 // All of the commands below do this implicitly.
 // Only the first invocation of this function will check the server version.
@@ -33,7 +34,11 @@
 int adb_connect(std::string_view service, std::string* _Nonnull error);
 
 // Same as above, except returning the TransportId for the service that we've connected to.
-int adb_connect(TransportId* _Nullable id, std::string_view service, std::string* _Nonnull error);
+// force_switch_device forces the function to attempt to select a device, even if the service
+// string appears to be a host: service (for use with host services that are device specific, like
+// forward).
+int adb_connect(TransportId* _Nullable id, std::string_view service, std::string* _Nonnull error,
+                bool force_switch_device = false);
 
 // Kill the currently running adb server, if it exists.
 bool adb_kill_server();
@@ -64,7 +69,7 @@
 
 // Reads a standard adb status response (OKAY|FAIL) and returns true in the
 // event of OKAY, false in the event of FAIL or protocol error.
-bool adb_status(int fd, std::string* _Nonnull error);
+bool adb_status(borrowed_fd fd, std::string* _Nonnull error);
 
 // Create a host command corresponding to selected transport type/serial.
 std::string format_host_command(const char* _Nonnull command);
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 16fa215..73dcde1 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -16,6 +16,7 @@
 
 #include "adb_install.h"
 
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -36,22 +37,33 @@
 #include "commandline.h"
 #include "fastdeploy.h"
 
-#if defined(ENABLE_FASTDEPLOY)
 static constexpr int kFastDeployMinApi = 24;
-#endif
+
+namespace {
+
+enum InstallMode {
+    INSTALL_DEFAULT,
+    INSTALL_PUSH,
+    INSTALL_STREAM,
+};
+
+}
 
 static bool can_use_feature(const char* feature) {
     FeatureSet features;
     std::string error;
     if (!adb_get_feature_set(&features, &error)) {
         fprintf(stderr, "error: %s\n", error.c_str());
-        return true;
+        return false;
     }
     return CanUseFeature(features, feature);
 }
 
-static bool use_legacy_install() {
-    return !can_use_feature(kFeatureCmd);
+static InstallMode best_install_mode() {
+    if (can_use_feature(kFeatureCmd)) {
+        return INSTALL_STREAM;
+    }
+    return INSTALL_PUSH;
 }
 
 static bool is_apex_supported() {
@@ -112,7 +124,7 @@
 }
 
 int uninstall_app(int argc, const char** argv) {
-    if (use_legacy_install()) {
+    if (best_install_mode() == INSTALL_PUSH) {
         return uninstall_app_legacy(argc, argv);
     }
     return uninstall_app_streamed(argc, argv);
@@ -132,15 +144,7 @@
     *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) {
+static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy) {
     printf("Performing Streamed Install\n");
 
     // The last argument must be the APK file
@@ -162,81 +166,80 @@
         error_exit("--fastdeploy doesn't support .apex files");
     }
 
-    if (use_fastdeploy == true) {
-#if defined(ENABLE_FASTDEPLOY)
-        TemporaryFile metadataTmpFile;
-        std::string patchTmpFilePath;
-        {
-            TemporaryFile patchTmpFile;
-            patchTmpFile.DoNotRemove();
-            patchTmpFilePath = patchTmpFile.path;
+    if (use_fastdeploy) {
+        auto metadata = extract_metadata(file);
+        if (metadata.has_value()) {
+            // pass all but 1st (command) and last (apk path) parameters through to pm for
+            // session creation
+            std::vector<const char*> pm_args{argv + 1, argv + argc - 1};
+            auto patchFd = install_patch(pm_args.size(), pm_args.data());
+            return stream_patch(file, std::move(metadata.value()), std::move(patchFd));
         }
+    }
 
-        FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
-        extract_metadata(file, metadataFile);
-        fclose(metadataFile);
-
-        create_patch(file, metadataTmpFile.path, patchTmpFilePath.c_str());
-        // pass all but 1st (command) and last (apk path) parameters through to pm for
-        // session creation
-        std::vector<const char*> pm_args{argv + 1, argv + argc - 1};
-        install_patch(file, patchTmpFilePath.c_str(), pm_args.size(), pm_args.data());
-        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) {
-            fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
-            return 1;
-        }
-
-        unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
-        if (local_fd < 0) {
-            fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
-            return 1;
-        }
-
-        std::string error;
-        std::string cmd = "exec:cmd package";
-
-        // don't copy the APK name, but, copy the rest of the arguments as-is
-        while (argc-- > 1) {
-            cmd += " " + escape_arg(std::string(*argv++));
-        }
-
-        // add size parameter [required for streaming installs]
-        // do last to override any user specified value
-        cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
-
-        if (is_apex) {
-            cmd += " --apex";
-        }
-
-        unique_fd remote_fd(adb_connect(cmd, &error));
-        if (remote_fd < 0) {
-            fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
-            return 1;
-        }
-
-        char buf[BUFSIZ];
-        copy_to_file(local_fd.get(), remote_fd.get());
-        read_status_line(remote_fd.get(), buf, sizeof(buf));
-
-        if (!strncmp("Success", buf, 7)) {
-            fputs(buf, stdout);
-            return 0;
-        }
-        fprintf(stderr, "adb: failed to install %s: %s", file, buf);
+    struct stat sb;
+    if (stat(file, &sb) == -1) {
+        fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
         return 1;
     }
+
+    unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
+    if (local_fd < 0) {
+        fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
+        return 1;
+    }
+
+#ifdef __linux__
+    posix_fadvise(local_fd.get(), 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
+#endif
+
+    const bool use_abb = can_use_feature(kFeatureAbbExec);
+    std::string error;
+    std::vector<std::string> cmd_args = {use_abb ? "package" : "exec:cmd package"};
+    cmd_args.reserve(argc + 3);
+
+    // don't copy the APK name, but, copy the rest of the arguments as-is
+    while (argc-- > 1) {
+        if (use_abb) {
+            cmd_args.push_back(*argv++);
+        } else {
+            cmd_args.push_back(escape_arg(*argv++));
+        }
+    }
+
+    // add size parameter [required for streaming installs]
+    // do last to override any user specified value
+    cmd_args.push_back("-S");
+    cmd_args.push_back(android::base::StringPrintf("%" PRIu64, static_cast<uint64_t>(sb.st_size)));
+
+    if (is_apex) {
+        cmd_args.push_back("--apex");
+    }
+
+    unique_fd remote_fd;
+    if (use_abb) {
+        remote_fd = send_abb_exec_command(cmd_args, &error);
+    } else {
+        remote_fd.reset(adb_connect(android::base::Join(cmd_args, " "), &error));
+    }
+    if (remote_fd < 0) {
+        fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
+        return 1;
+    }
+
+    copy_to_file(local_fd.get(), remote_fd.get());
+
+    char buf[BUFSIZ];
+    read_status_line(remote_fd.get(), buf, sizeof(buf));
+    if (!strncmp("Success", buf, 7)) {
+        fputs(buf, stdout);
+        return 0;
+    }
+    fprintf(stderr, "adb: failed to install %s: %s", file, buf);
+    return 1;
 }
 
-static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,
-                              bool use_localagent) {
+static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy) {
     printf("Performing Push Install\n");
 
     // Find last APK argument.
@@ -256,50 +259,35 @@
 
     int result = -1;
     std::vector<const char*> apk_file = {argv[last_apk]};
-    std::string apk_dest =
-            "/data/local/tmp/" + android::base::Basename(argv[last_apk]);
-
-    if (use_fastdeploy == true) {
-#if defined(ENABLE_FASTDEPLOY)
-        TemporaryFile metadataTmpFile;
-        TemporaryFile patchTmpFile;
-
-        FILE* metadataFile = fopen(metadataTmpFile.path, "wb");
-        extract_metadata(apk_file[0], metadataFile);
-        fclose(metadataFile);
-
-        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;
-    }
-
+    std::string apk_dest = "/data/local/tmp/" + android::base::Basename(argv[last_apk]);
     argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
-    result = pm_command(argc, argv);
 
-cleanup_apk:
-    if (use_fastdeploy == true) {
-#if defined(ENABLE_FASTDEPLOY)
-        delete_device_patch_file(apk_file[0]);
-#endif
+    if (use_fastdeploy) {
+        auto metadata = extract_metadata(apk_file[0]);
+        if (metadata.has_value()) {
+            auto patchFd = apply_patch_on_device(apk_dest.c_str());
+            int status = stream_patch(apk_file[0], std::move(metadata.value()), std::move(patchFd));
+
+            result = pm_command(argc, argv);
+            delete_device_file(apk_dest);
+
+            return status;
+        }
     }
-    delete_device_file(apk_dest);
+
+    if (do_sync_push(apk_file, apk_dest.c_str(), false)) {
+        result = pm_command(argc, argv);
+        delete_device_file(apk_dest);
+    }
+
     return result;
 }
 
 int install_app(int argc, const char** argv) {
     std::vector<int> processedArgIndicies;
-    enum installMode {
-        INSTALL_DEFAULT,
-        INSTALL_PUSH,
-        INSTALL_STREAM
-    } installMode = INSTALL_DEFAULT;
+    InstallMode installMode = INSTALL_DEFAULT;
     bool use_fastdeploy = false;
     bool is_reinstall = false;
-    bool use_localagent = false;
     FastDeploy_AgentUpdateStrategy agent_update_strategy = FastDeploy_AgentUpdateDifferentVersion;
 
     for (int i = 1; i < argc; i++) {
@@ -328,34 +316,24 @@
         } else if (!strcmp(argv[i], "--version-check-agent")) {
             processedArgIndicies.push_back(i);
             agent_update_strategy = FastDeploy_AgentUpdateDifferentVersion;
-#ifndef _WIN32
-        } else if (!strcmp(argv[i], "--local-agent")) {
-            processedArgIndicies.push_back(i);
-            use_localagent = true;
-#endif
         }
     }
 
     if (installMode == INSTALL_DEFAULT) {
-        if (use_legacy_install()) {
-            installMode = INSTALL_PUSH;
-        } else {
-            installMode = INSTALL_STREAM;
-        }
+        installMode = best_install_mode();
     }
 
-    if (installMode == INSTALL_STREAM && use_legacy_install() == true) {
+    if (installMode == INSTALL_STREAM && best_install_mode() == INSTALL_PUSH) {
         error_exit("Attempting to use streaming install on unsupported device");
     }
 
-#if defined(ENABLE_FASTDEPLOY)
-    if (use_fastdeploy == true && get_device_api_level() < kFastDeployMinApi) {
+    if (use_fastdeploy && 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
+    fastdeploy_set_agent_update_strategy(agent_update_strategy);
 
     std::vector<const char*> passthrough_argv;
     for (int i = 0; i < argc; i++) {
@@ -368,26 +346,13 @@
         error_exit("install requires an apk argument");
     }
 
-    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) {
         case INSTALL_PUSH:
             return install_app_legacy(passthrough_argv.size(), passthrough_argv.data(),
-                                      use_fastdeploy, use_localagent);
+                                      use_fastdeploy);
         case INSTALL_STREAM:
             return install_app_streamed(passthrough_argv.size(), passthrough_argv.data(),
-                                        use_fastdeploy, use_localagent);
+                                        use_fastdeploy);
         case INSTALL_DEFAULT:
         default:
             return 1;
@@ -409,7 +374,8 @@
             android::base::EndsWithIgnoreCase(file, ".dm") ||
             android::base::EndsWithIgnoreCase(file, ".fsv_sig")) {
             struct stat sb;
-            if (stat(file, &sb) != -1) total_size += sb.st_size;
+            if (stat(file, &sb) == -1) perror_exit("failed to stat \"%s\"", file);
+            total_size += sb.st_size;
             first_apk = i;
         } else {
             break;
@@ -419,7 +385,7 @@
     if (first_apk == -1) error_exit("need APK file on command line");
 
     std::string install_cmd;
-    if (use_legacy_install()) {
+    if (best_install_mode() == INSTALL_PUSH) {
         install_cmd = "exec:pm";
     } else {
         install_cmd = "exec:cmd package";
@@ -459,13 +425,13 @@
     }
 
     // Valid session, now stream the APKs
-    int success = 1;
+    bool success = true;
     for (int i = first_apk; i < argc; i++) {
         const char* file = argv[i];
         struct stat sb;
         if (stat(file, &sb) == -1) {
-            fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
-            success = 0;
+            fprintf(stderr, "adb: failed to stat \"%s\": %s\n", file, strerror(errno));
+            success = false;
             goto finalize_session;
         }
 
@@ -476,8 +442,8 @@
 
         unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
         if (local_fd < 0) {
-            fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
-            success = 0;
+            fprintf(stderr, "adb: failed to open \"%s\": %s\n", file, strerror(errno));
+            success = false;
             goto finalize_session;
         }
 
@@ -485,7 +451,7 @@
         unique_fd remote_fd(adb_connect(cmd, &error));
         if (remote_fd < 0) {
             fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
-            success = 0;
+            success = false;
             goto finalize_session;
         }
 
@@ -493,15 +459,15 @@
         read_status_line(remote_fd.get(), buf, sizeof(buf));
 
         if (strncmp("Success", buf, 7)) {
-            fprintf(stderr, "adb: failed to write %s\n", file);
+            fprintf(stderr, "adb: failed to write \"%s\"\n", file);
             fputs(buf, stderr);
-            success = 0;
+            success = false;
             goto finalize_session;
         }
     }
 
 finalize_session:
-    // Commit session if we streamed everything okay; otherwise abandon
+    // Commit session if we streamed everything okay; otherwise abandon.
     std::string service = android::base::StringPrintf("%s install-%s %d", install_cmd.c_str(),
                                                       success ? "commit" : "abandon", session_id);
     {
@@ -512,14 +478,16 @@
         }
         read_status_line(fd.get(), buf, sizeof(buf));
     }
+    if (!success) return EXIT_FAILURE;
 
-    if (!strncmp("Success", buf, 7)) {
-        fputs(buf, stdout);
-        return 0;
+    if (strncmp("Success", buf, 7)) {
+        fprintf(stderr, "adb: failed to finalize session\n");
+        fputs(buf, stderr);
+        return EXIT_FAILURE;
     }
-    fprintf(stderr, "adb: failed to finalize session\n");
-    fputs(buf, stderr);
-    return EXIT_FAILURE;
+
+    fputs(buf, stdout);
+    return EXIT_SUCCESS;
 }
 
 int install_multi_package(int argc, const char** argv) {
@@ -542,7 +510,7 @@
 
     if (first_package == -1) error_exit("need APK or APEX files on command line");
 
-    if (use_legacy_install()) {
+    if (best_install_mode() == INSTALL_PUSH) {
         fprintf(stderr, "adb: multi-package install is not supported on this device\n");
         return EXIT_FAILURE;
     }
@@ -739,6 +707,20 @@
 }
 
 int delete_device_file(const std::string& filename) {
-    std::string cmd = "rm -f " + escape_arg(filename);
-    return send_shell_command(cmd);
+    // http://b/17339227 "Sideloading a Readonly File Results in a Prompt to
+    // Delete" caused us to add `-f` here, to avoid the equivalent of the `-i`
+    // prompt that you get from BSD rm (used in Android 5) if you have a
+    // non-writable file and stdin is a tty (which is true for old versions of
+    // adbd).
+    //
+    // Unfortunately, `rm -f` requires Android 4.3, so that workaround broke
+    // earlier Android releases. This was reported as http://b/37704384 "adb
+    // install -r passes invalid argument to rm on Android 4.1" and
+    // http://b/37035817 "ADB Fails: rm failed for -f, No such file or
+    // directory".
+    //
+    // Testing on a variety of devices and emulators shows that redirecting
+    // stdin is sufficient to avoid the pseudo-`-i`, and works on toolbox,
+    // BSD, and toybox versions of rm.
+    return send_shell_command("rm " + escape_arg(filename) + " </dev/null");
 }
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index 3eee426..e8be784 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -53,6 +53,25 @@
     *new std::map<std::string, std::shared_ptr<RSA>>;
 static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
 
+static std::string get_user_info() {
+    std::string hostname;
+    if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
+#if !defined(_WIN32)
+    char buf[64];
+    if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
+#endif
+    if (hostname.empty()) hostname = "unknown";
+
+    std::string username;
+    if (getenv("LOGNAME")) username = getenv("LOGNAME");
+#if !defined(_WIN32)
+    if (username.empty() && getlogin()) username = getlogin();
+#endif
+    if (username.empty()) hostname = "unknown";
+
+    return " " + username + "@" + hostname;
+}
+
 static bool calculate_public_key(std::string* out, RSA* private_key) {
     uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
     if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
@@ -70,6 +89,7 @@
     size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(out->data()), binary_key_data,
                                            sizeof(binary_key_data));
     out->resize(actual_length);
+    out->append(get_user_info());
     return true;
 }
 
@@ -79,6 +99,7 @@
     mode_t old_mask;
     FILE *f = nullptr;
     int ret = 0;
+    std::string pubkey;
 
     EVP_PKEY* pkey = EVP_PKEY_new();
     BIGNUM* exponent = BN_new();
@@ -92,6 +113,11 @@
     RSA_generate_key_ex(rsa, 2048, exponent, nullptr);
     EVP_PKEY_set1_RSA(pkey, rsa);
 
+    if (!calculate_public_key(&pubkey, rsa)) {
+        LOG(ERROR) << "failed to calculate public key";
+        goto out;
+    }
+
     old_mask = umask(077);
 
     f = fopen(file.c_str(), "w");
@@ -104,7 +130,12 @@
     umask(old_mask);
 
     if (!PEM_write_PrivateKey(f, pkey, nullptr, nullptr, 0, nullptr, nullptr)) {
-        D("Failed to write key");
+        LOG(ERROR) << "Failed to write key";
+        goto out;
+    }
+
+    if (!android::base::WriteStringToFile(pubkey, file + ".pub")) {
+        PLOG(ERROR) << "failed to write public key";
         goto out;
     }
 
@@ -142,7 +173,8 @@
 
     RSA* key = RSA_new();
     if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
-        LOG(ERROR) << "Failed to read key";
+        LOG(ERROR) << "Failed to read key from '" << file << "'";
+        ERR_print_errors_fp(stderr);
         RSA_free(key);
         return nullptr;
     }
@@ -218,7 +250,7 @@
     return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
 }
 
-static bool generate_userkey() {
+static bool load_userkey() {
     std::string path = get_user_key_path();
     if (path.empty()) {
         PLOG(ERROR) << "Error getting user key filename";
@@ -404,8 +436,8 @@
 void adb_auth_init() {
     LOG(INFO) << "adb_auth_init...";
 
-    if (!generate_userkey()) {
-        LOG(ERROR) << "Failed to generate user key";
+    if (!load_userkey()) {
+        LOG(ERROR) << "Failed to load (or generate) user key";
         return;
     }
 
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 8dd85d7..813a8a9 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -96,9 +96,8 @@
         " version                  show version num\n"
         "\n"
         "networking:\n"
-        " connect HOST[:PORT]      connect to a device via TCP/IP [default port=5555]\n"
-        " disconnect [HOST[:PORT]]\n"
-        "     disconnect from given TCP/IP device [default port=5555], or all\n"
+        " connect HOST[:PORT]      connect to a device via TCP/IP\n"
+        " disconnect [[HOST]:PORT] disconnect from given TCP/IP device, or all\n"
         " forward --list           list all forward socket connections\n"
         " forward [--no-rebind] LOCAL REMOTE\n"
         "     forward socket connection using:\n"
@@ -108,6 +107,7 @@
         "       localfilesystem:<unix domain socket name>\n"
         "       dev:<character device name>\n"
         "       jdwp:<process pid> (remote only)\n"
+        "       acceptfd:<fd> (listen only)\n"
         " forward --remove LOCAL   remove specific forward socket connection\n"
         " forward --remove-all     remove all forward socket connections\n"
         " ppp TTY [PARAMETER...]   run PPP over USB\n"
@@ -128,17 +128,17 @@
         " pull [-a] REMOTE... LOCAL\n"
         "     copy files/dirs from device\n"
         "     -a: preserve file timestamp and mode\n"
-        " sync [all|data|odm|oem|product_services|product|system|vendor]\n"
+        " sync [all|data|odm|oem|product|system|system_ext|vendor]\n"
         "     sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
-        "     -l: list but don't copy\n"
+        "     -l: list files that would be copied, but don't copy them\n"
         "\n"
         "shell:\n"
         " shell [-e ESCAPE] [-n] [-Tt] [-x] [COMMAND...]\n"
         "     run remote shell command (interactive shell if no command given)\n"
         "     -e: choose escape character, or \"none\"; default '~'\n"
         "     -n: don't read from stdin\n"
-        "     -T: disable PTY allocation\n"
-        "     -t: force PTY allocation\n"
+        "     -T: disable pty allocation\n"
+        "     -t: allocate a pty if on a tty (-tt: force pty allocation)\n"
         "     -x: disable remote exit codes and stdout/stderr separation\n"
         " emu COMMAND              run emulator console command\n"
         "\n"
@@ -154,6 +154,7 @@
         "     -d: allow version code downgrade (debuggable packages only)\n"
         "     -p: partial application install (install-multiple only)\n"
         "     -g: grant all runtime permissions\n"
+        "     --abi ABI: override platform's default ABI\n"
         "     --instant: cause the app to be installed as an ephemeral install app\n"
         "     --no-streaming: always push APK to device and invoke Package Manager as separate steps\n"
         "     --streaming: force streaming APK directly into Package Manager\n"
@@ -165,14 +166,12 @@
 #ifndef _WIN32
         "     --local-agent: locate agent files from local source build (instead of SDK location)\n"
 #endif
+        "     (See also `adb shell pm help` for more options.)\n"
         //TODO--installlog <filename>
         " uninstall [-k] PACKAGE\n"
         "     remove this app package from the device\n"
         "     '-k': keep the data and cache directories\n"
         "\n"
-        "backup/restore:\n"
-        "   to show usage run \"adb shell bu help\"\n"
-        "\n"
         "debugging:\n"
         " bugreport [PATH]\n"
         "     write bugreport to given PATH [default=bugreport.zip];\n"
@@ -257,13 +256,8 @@
 }
 #endif
 
-// Reads from |fd| and prints received data. If |use_shell_protocol| is true
-// this expects that incoming data will use the shell protocol, in which case
-// stdout/stderr are routed independently and the remote exit code will be
-// returned.
-// if |callback| is non-null, stdout/stderr output will be handled by it.
-int read_and_dump(int fd, bool use_shell_protocol = false,
-                  StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK) {
+int read_and_dump(borrowed_fd fd, bool use_shell_protocol,
+                  StandardStreamsCallbackInterface* callback) {
     int exit_code = 0;
     if (fd < 0) return exit_code;
 
@@ -305,9 +299,9 @@
             }
             length = protocol->data_length();
         } else {
-            D("read_and_dump(): pre adb_read(fd=%d)", fd);
+            D("read_and_dump(): pre adb_read(fd=%d)", fd.get());
             length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
-            D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
+            D("read_and_dump(): post adb_read(fd=%d): length=%d", fd.get(), length);
             if (length <= 0) {
                 break;
             }
@@ -359,7 +353,7 @@
 }
 
 void copy_to_file(int inFd, int outFd) {
-    std::vector<char> buf(32 * 1024);
+    std::vector<char> buf(64 * 1024);
     int len;
     long total = 0;
     int old_stdin_mode = -1;
@@ -778,17 +772,16 @@
         error_exit("abb is not supported by the device");
     }
 
+    optind = 1;  // argv[0] is always "abb", so set `optind` appropriately.
+
     // Defaults.
     constexpr char escape_char = '~';  // -e
     constexpr bool use_shell_protocol = true;
     constexpr auto shell_type_arg = kShellServiceArgRaw;
     constexpr bool empty_command = false;
 
-    std::string service_string("abb:");
-    for (auto i = optind; i < argc; ++i) {
-        service_string.append(argv[i]);
-        service_string.push_back(ABB_ARG_DELIMETER);
-    }
+    std::vector<const char*> args(argv + optind, argv + argc);
+    std::string service_string = "abb:" + android::base::Join(args, ABB_ARG_DELIMETER);
 
     D("abb -e 0x%x [%*.s]\n", escape_char, static_cast<int>(service_string.size()),
       service_string.data());
@@ -887,7 +880,7 @@
             return -1;
         }
         fprintf(stderr, "adb: trying pre-KitKat sideload method...\n");
-        return adb_sideload_legacy(filename, package_fd, static_cast<int>(sb.st_size));
+        return adb_sideload_legacy(filename, package_fd.get(), static_cast<int>(sb.st_size));
     }
 
     int opt = SIDELOAD_HOST_BLOCK_SIZE;
@@ -1142,7 +1135,7 @@
     // If we were using a specific transport ID, there's nothing we can wait for.
     if (previous_id == 0) {
         adb_set_transport(previous_type, previous_serial, 0);
-        wait_for_device("wait-for-device", 3000ms);
+        wait_for_device("wait-for-device", 6000ms);
     }
 
     return true;
@@ -1207,14 +1200,14 @@
     return send_shell_command(cmd);
 }
 
-static void write_zeros(int bytes, int fd) {
+static void write_zeros(int bytes, borrowed_fd fd) {
     int old_stdin_mode = -1;
     int old_stdout_mode = -1;
     std::vector<char> buf(bytes);
 
-    D("write_zeros(%d) -> %d", bytes, fd);
+    D("write_zeros(%d) -> %d", bytes, fd.get());
 
-    stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
+    stdinout_raw_prologue(-1, fd.get(), old_stdin_mode, old_stdout_mode);
 
     if (fd == STDOUT_FILENO) {
         fwrite(buf.data(), 1, bytes, stdout);
@@ -1223,12 +1216,14 @@
         adb_write(fd, buf.data(), bytes);
     }
 
-    stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
+    stdinout_raw_prologue(-1, fd.get(), old_stdin_mode, old_stdout_mode);
 
     D("write_zeros() finished");
 }
 
 static int backup(int argc, const char** argv) {
+    fprintf(stdout, "WARNING: adb backup is deprecated and may be removed in a future release\n");
+
     const char* filename = "backup.ab";
 
     /* find, extract, and use any -f argument */
@@ -1278,6 +1273,8 @@
 }
 
 static int restore(int argc, const char** argv) {
+    fprintf(stdout, "WARNING: adb restore is deprecated and may be removed in a future release\n");
+
     if (argc != 2) error_exit("restore requires an argument");
 
     const char* filename = argv[1];
@@ -1615,13 +1612,13 @@
         return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "connect")) {
-        if (argc != 2) error_exit("usage: adb connect <host>[:<port>]");
+        if (argc != 2) error_exit("usage: adb connect HOST[:PORT>]");
 
         std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
         return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "disconnect")) {
-        if (argc > 2) error_exit("usage: adb disconnect [<host>[:<port>]]");
+        if (argc > 2) error_exit("usage: adb disconnect [HOST[:PORT]]");
 
         std::string query = android::base::StringPrintf("host:disconnect:%s",
                                                         (argc == 2) ? argv[1] : "");
@@ -1703,10 +1700,27 @@
             error_exit("tcpip: invalid port: %s", argv[1]);
         }
         return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
+    } else if (!strcmp(argv[0], "remount")) {
+        FeatureSet features;
+        std::string error;
+        if (!adb_get_feature_set(&features, &error)) {
+            fprintf(stderr, "error: %s\n", error.c_str());
+            return 1;
+        }
+
+        if (CanUseFeature(features, kFeatureRemountShell)) {
+            std::vector<const char*> args = {"shell"};
+            args.insert(args.cend(), argv, argv + argc);
+            return adb_shell(args.size(), args.data());
+        } else if (argc > 1) {
+            auto command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
+            return adb_connect_command(command);
+        } else {
+            return adb_connect_command("remount:");
+        }
     }
     // clang-format off
-    else if (!strcmp(argv[0], "remount") ||
-             !strcmp(argv[0], "reboot") ||
+    else if (!strcmp(argv[0], "reboot") ||
              !strcmp(argv[0], "reboot-bootloader") ||
              !strcmp(argv[0], "reboot-fastboot") ||
              !strcmp(argv[0], "usb") ||
@@ -1738,41 +1752,33 @@
         // Determine the <host-prefix> for this command.
         std::string host_prefix;
         if (reverse) {
-            host_prefix = "reverse";
+            host_prefix = "reverse:";
         } else {
-            if (serial) {
-                host_prefix = android::base::StringPrintf("host-serial:%s", serial);
-            } else if (transport_type == kTransportUsb) {
-                host_prefix = "host-usb";
-            } else if (transport_type == kTransportLocal) {
-                host_prefix = "host-local";
-            } else {
-                host_prefix = "host";
-            }
+            host_prefix = "host:";
         }
 
         std::string cmd, error_message;
         if (strcmp(argv[0], "--list") == 0) {
             if (argc != 1) error_exit("--list doesn't take any arguments");
-            return adb_query_command(host_prefix + ":list-forward");
+            return adb_query_command(host_prefix + "list-forward");
         } else if (strcmp(argv[0], "--remove-all") == 0) {
             if (argc != 1) error_exit("--remove-all doesn't take any arguments");
-            cmd = host_prefix + ":killforward-all";
+            cmd = "killforward-all";
         } else if (strcmp(argv[0], "--remove") == 0) {
             // forward --remove <local>
             if (argc != 2) error_exit("--remove requires an argument");
-            cmd = host_prefix + ":killforward:" + argv[1];
+            cmd = std::string("killforward:") + argv[1];
         } else if (strcmp(argv[0], "--no-rebind") == 0) {
             // forward --no-rebind <local> <remote>
             if (argc != 3) error_exit("--no-rebind takes two arguments");
             if (forward_targets_are_valid(argv[1], argv[2], &error_message)) {
-                cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
+                cmd = std::string("forward:norebind:") + argv[1] + ";" + argv[2];
             }
         } else {
             // forward <local> <remote>
             if (argc != 2) error_exit("forward takes two arguments");
             if (forward_targets_are_valid(argv[0], argv[1], &error_message)) {
-                cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
+                cmd = std::string("forward:") + argv[0] + ";" + argv[1];
             }
         }
 
@@ -1780,7 +1786,7 @@
             error_exit("error: %s", error_message.c_str());
         }
 
-        unique_fd fd(adb_connect(cmd, &error_message));
+        unique_fd fd(adb_connect(nullptr, host_prefix + cmd, &error_message, true));
         if (fd < 0 || !adb_status(fd.get(), &error_message)) {
             error_exit("error: %s", error_message.c_str());
         }
@@ -1822,7 +1828,7 @@
         if (argc < 2) error_exit("install-multiple requires an argument");
         return install_multiple_app(argc, argv);
     } else if (!strcmp(argv[0], "install-multi-package")) {
-        if (argc < 3) error_exit("install-multi-package requires an argument");
+        if (argc < 2) error_exit("install-multi-package requires an argument");
         return install_multi_package(argc, argv);
     } else if (!strcmp(argv[0], "uninstall")) {
         if (argc < 2) error_exit("uninstall requires an argument");
@@ -1842,8 +1848,8 @@
         }
 
         if (src.empty()) src = "all";
-        std::vector<std::string> partitions{"data",   "odm",   "oem", "product", "product_services",
-                                            "system", "vendor"};
+        std::vector<std::string> partitions{"data",   "odm",        "oem",   "product",
+                                            "system", "system_ext", "vendor"};
         bool found = false;
         for (const auto& partition : partitions) {
             if (src == "all" || src == partition) {
@@ -1891,7 +1897,10 @@
     } else if (!strcmp(argv[0], "track-jdwp")) {
         return adb_connect_command("track-jdwp");
     } else if (!strcmp(argv[0], "track-devices")) {
-        return adb_connect_command("host:track-devices");
+        if (argc > 2 || (argc == 2 && strcmp(argv[1], "-l"))) {
+            error_exit("usage: adb track-devices [-l]");
+        }
+        return adb_connect_command(argc == 2 ? "host:track-devices-l" : "host:track-devices");
     } else if (!strcmp(argv[0], "raw")) {
         if (argc != 2) {
             error_exit("usage: adb raw SERVICE");
diff --git a/adb/client/commandline.h b/adb/client/commandline.h
index 6cfd4f7..ab77b29 100644
--- a/adb/client/commandline.h
+++ b/adb/client/commandline.h
@@ -17,7 +17,11 @@
 #ifndef COMMANDLINE_H
 #define COMMANDLINE_H
 
+#include <android-base/strings.h>
+
 #include "adb.h"
+#include "adb_client.h"
+#include "adb_unique_fd.h"
 
 // Callback used to handle the standard streams (stdout and stderr) sent by the
 // device's upon receiving a command.
@@ -105,4 +109,25 @@
         const std::string& command, bool disable_shell_protocol = false,
         StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
 
+// Reads from |fd| and prints received data. If |use_shell_protocol| is true
+// this expects that incoming data will use the shell protocol, in which case
+// stdout/stderr are routed independently and the remote exit code will be
+// returned.
+// if |callback| is non-null, stdout/stderr output will be handled by it.
+int read_and_dump(borrowed_fd fd, bool use_shell_protocol = false,
+                  StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);
+
+// Connects to the device "abb" service with |command| and returns the fd.
+template <typename ContainerT>
+unique_fd send_abb_exec_command(const ContainerT& command_args, std::string* error) {
+    std::string service_string = "abb_exec:" + android::base::Join(command_args, ABB_ARG_DELIMETER);
+
+    unique_fd fd(adb_connect(service_string, error));
+    if (fd < 0) {
+        fprintf(stderr, "adb: failed to run abb_exec. Error: %s\n", error->c_str());
+        return unique_fd{};
+    }
+    return fd;
+}
+
 #endif  // COMMANDLINE_H
diff --git a/adb/client/console.cpp b/adb/client/console.cpp
index 1dbb6e2..d10f4de 100644
--- a/adb/client/console.cpp
+++ b/adb/client/console.cpp
@@ -71,7 +71,7 @@
         return -1;
     }
 
-    int port;
+    int port = -1;
     size_t emulator_count = 0;
     for (const auto& device : android::base::Split(devices, "\n")) {
         if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index f4e8664..5fa0edb 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -27,124 +27,112 @@
 #include "androidfw/ZipFileRO.h"
 #include "client/file_sync_client.h"
 #include "commandline.h"
+#include "deployagent.inc"        // Generated include via build rule.
+#include "deployagentscript.inc"  // Generated include via build rule.
+#include "fastdeploy/deploypatchgenerator/deploy_patch_generator.h"
+#include "fastdeploy/deploypatchgenerator/patch_utils.h"
+#include "fastdeploy/proto/ApkEntry.pb.h"
 #include "fastdeploycallbacks.h"
 #include "sysdeps.h"
 
 #include "adb_utils.h"
 
-static constexpr long kRequiredAgentVersion = 0x00000002;
+static constexpr long kRequiredAgentVersion = 0x00000003;
 
-static constexpr const char* kDeviceAgentPath = "/data/local/tmp/";
+static constexpr int kPackageMissing = 3;
+static constexpr int kInvalidAgentVersion = 4;
 
-static bool g_use_localagent = false;
+static constexpr const char* kDeviceAgentFile = "/data/local/tmp/deployagent.jar";
+static constexpr const char* kDeviceAgentScript = "/data/local/tmp/deployagent";
 
-long get_agent_version() {
-    std::vector<char> versionOutputBuffer;
-    std::vector<char> versionErrorBuffer;
+static constexpr bool g_verbose_timings = false;
+static FastDeploy_AgentUpdateStrategy g_agent_update_strategy =
+        FastDeploy_AgentUpdateDifferentVersion;
 
-    int statusCode = capture_shell_command("/data/local/tmp/deployagent version",
-                                           &versionOutputBuffer, &versionErrorBuffer);
-    long version = -1;
+using APKMetaData = com::android::fastdeploy::APKMetaData;
 
-    if (statusCode == 0 && versionOutputBuffer.size() > 0) {
-        version = strtol((char*)versionOutputBuffer.data(), NULL, 16);
+namespace {
+
+struct TimeReporter {
+    TimeReporter(const char* label) : label_(label) {}
+    ~TimeReporter() {
+        if (g_verbose_timings) {
+            auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+                    std::chrono::steady_clock::now() - start_);
+            fprintf(stderr, "%s finished in %lldms\n", label_,
+                    static_cast<long long>(duration.count()));
+        }
     }
 
-    return version;
-}
+  private:
+    const char* label_;
+    std::chrono::steady_clock::time_point start_ = std::chrono::steady_clock::now();
+};
+#define REPORT_FUNC_TIME() TimeReporter reporter(__func__)
+
+struct FileDeleter {
+    FileDeleter(const char* path) : path_(path) {}
+    ~FileDeleter() { adb_unlink(path_); }
+
+  private:
+    const char* const path_;
+};
+
+}  // namespace
 
 int get_device_api_level() {
-    std::vector<char> sdkVersionOutputBuffer;
-    std::vector<char> sdkVersionErrorBuffer;
+    REPORT_FUNC_TIME();
+    std::vector<char> sdk_version_output_buffer;
+    std::vector<char> sdk_version_error_buffer;
     int api_level = -1;
 
-    int statusCode = capture_shell_command("getprop ro.build.version.sdk", &sdkVersionOutputBuffer,
-                                           &sdkVersionErrorBuffer);
-    if (statusCode == 0 && sdkVersionOutputBuffer.size() > 0) {
-        api_level = strtol((char*)sdkVersionOutputBuffer.data(), NULL, 10);
+    int statusCode = capture_shell_command("getprop ro.build.version.sdk",
+                                           &sdk_version_output_buffer, &sdk_version_error_buffer);
+    if (statusCode == 0 && sdk_version_output_buffer.size() > 0) {
+        api_level = strtol((char*)sdk_version_output_buffer.data(), NULL, 10);
     }
 
     return api_level;
 }
 
-void fastdeploy_set_local_agent(bool use_localagent) {
-    g_use_localagent = use_localagent;
+void fastdeploy_set_agent_update_strategy(FastDeploy_AgentUpdateStrategy agent_update_strategy) {
+    g_agent_update_strategy = agent_update_strategy;
 }
 
-// local_path - must start with a '/' and be relative to $ANDROID_PRODUCT_OUT
-static std::string get_agent_component_host_path(const char* local_path, const char* sdk_path) {
-    std::string adb_dir = android::base::GetExecutableDirectory();
-    if (adb_dir.empty()) {
-        error_exit("Could not determine location of adb!");
-    }
-
-    if (g_use_localagent) {
-        const char* product_out = getenv("ANDROID_PRODUCT_OUT");
-        if (product_out == nullptr) {
-            error_exit("Could not locate %s because $ANDROID_PRODUCT_OUT is not defined",
-                       local_path);
-        }
-        return android::base::StringPrintf("%s%s", product_out, local_path);
-    } else {
-        return adb_dir + sdk_path;
-    }
-}
-
-static bool deploy_agent(bool checkTimeStamps) {
+static void push_to_device(const void* data, size_t byte_count, const char* dst, bool sync) {
     std::vector<const char*> srcs;
-    std::string jar_path =
-            get_agent_component_host_path("/system/framework/deployagent.jar", "/deployagent.jar");
-    std::string script_path =
-            get_agent_component_host_path("/system/bin/deployagent", "/deployagent");
-    srcs.push_back(jar_path.c_str());
-    srcs.push_back(script_path.c_str());
+    TemporaryFile tf;
+    android::base::WriteFully(tf.fd, data, byte_count);
+    srcs.push_back(tf.path);
+    // On Windows, the file needs to be flushed before pushing to device,
+    // but can't be removed until after the push.
+    unix_close(tf.release());
 
-    if (do_sync_push(srcs, kDeviceAgentPath, checkTimeStamps)) {
-        // on windows the shell script might have lost execute permission
-        // so need to set this explicitly
-        const char* kChmodCommandPattern = "chmod 777 %sdeployagent";
-        std::string chmodCommand =
-                android::base::StringPrintf(kChmodCommandPattern, kDeviceAgentPath);
-        int ret = send_shell_command(chmodCommand);
-        if (ret != 0) {
-            error_exit("Error executing %s returncode: %d", chmodCommand.c_str(), ret);
-        }
-    } else {
-        error_exit("Error pushing agent files to device");
+    if (!do_sync_push(srcs, dst, sync)) {
+        error_exit("Failed to push fastdeploy agent to device.");
+    }
+}
+
+static bool deploy_agent(bool check_time_stamps) {
+    REPORT_FUNC_TIME();
+
+    push_to_device(kDeployAgent, sizeof(kDeployAgent), kDeviceAgentFile, check_time_stamps);
+    push_to_device(kDeployAgentScript, sizeof(kDeployAgentScript), kDeviceAgentScript,
+                   check_time_stamps);
+
+    // on windows the shell script might have lost execute permission
+    // so need to set this explicitly
+    const char* kChmodCommandPattern = "chmod 777 %s";
+    std::string chmod_command =
+            android::base::StringPrintf(kChmodCommandPattern, kDeviceAgentScript);
+    int ret = send_shell_command(chmod_command);
+    if (ret != 0) {
+        error_exit("Error executing %s returncode: %d", chmod_command.c_str(), ret);
     }
 
     return true;
 }
 
-void update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy) {
-    long agent_version = get_agent_version();
-    switch (agentUpdateStrategy) {
-        case FastDeploy_AgentUpdateAlways:
-            deploy_agent(false);
-            break;
-        case FastDeploy_AgentUpdateNewerTimeStamp:
-            deploy_agent(true);
-            break;
-        case FastDeploy_AgentUpdateDifferentVersion:
-            if (agent_version != kRequiredAgentVersion) {
-                if (agent_version < 0) {
-                    printf("Could not detect agent on device, deploying\n");
-                } else {
-                    printf("Device agent version is (%ld), (%ld) is required, re-deploying\n",
-                           agent_version, kRequiredAgentVersion);
-                }
-                deploy_agent(false);
-            }
-            break;
-    }
-
-    agent_version = get_agent_version();
-    if (agent_version != kRequiredAgentVersion) {
-        error_exit("After update agent version remains incorrect! Expected %ld but version is %ld",
-                   kRequiredAgentVersion, agent_version);
-    }
-}
-
 static std::string get_string_from_utf16(const char16_t* input, int input_len) {
     ssize_t utf8_length = utf16_to_utf8_length(input, input_len);
     if (utf8_length <= 0) {
@@ -156,29 +144,29 @@
     return utf8;
 }
 
-static std::string get_packagename_from_apk(const char* apkPath) {
+static std::string get_package_name_from_apk(const char* apk_path) {
 #undef open
-    std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
+    std::unique_ptr<android::ZipFileRO> zip_file((android::ZipFileRO::open)(apk_path));
 #define open ___xxx_unix_open
-    if (zipFile == nullptr) {
-        perror_exit("Could not open %s", apkPath);
+    if (zip_file == nullptr) {
+        perror_exit("Could not open %s", apk_path);
     }
-    android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
+    android::ZipEntryRO entry = zip_file->findEntryByName("AndroidManifest.xml");
     if (entry == nullptr) {
-        error_exit("Could not find AndroidManifest.xml inside %s", apkPath);
+        error_exit("Could not find AndroidManifest.xml inside %s", apk_path);
     }
     uint32_t manifest_len = 0;
-    if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
-        error_exit("Could not read AndroidManifest.xml inside %s", apkPath);
+    if (!zip_file->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
+        error_exit("Could not read AndroidManifest.xml inside %s", apk_path);
     }
     std::vector<char> manifest_data(manifest_len);
-    if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
-        error_exit("Could not uncompress AndroidManifest.xml inside %s", apkPath);
+    if (!zip_file->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
+        error_exit("Could not uncompress AndroidManifest.xml inside %s", apk_path);
     }
     android::ResXMLTree tree;
     android::status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
     if (setto_status != android::OK) {
-        error_exit("Could not parse AndroidManifest.xml inside %s", apkPath);
+        error_exit("Could not parse AndroidManifest.xml inside %s", apk_path);
     }
     android::ResXMLParser::event_code_t code;
     while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
@@ -219,99 +207,97 @@
                 break;
         }
     }
-    error_exit("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
+    error_exit("Could not find package name tag in AndroidManifest.xml inside %s", apk_path);
 }
 
-void extract_metadata(const char* apkPath, FILE* outputFp) {
-    std::string packageName = get_packagename_from_apk(apkPath);
-    const char* kAgentExtractCommandPattern = "/data/local/tmp/deployagent extract %s";
-    std::string extractCommand =
-            android::base::StringPrintf(kAgentExtractCommandPattern, packageName.c_str());
+static long parse_agent_version(const std::vector<char>& version_buffer) {
+    long version = -1;
+    if (!version_buffer.empty()) {
+        version = strtol((char*)version_buffer.data(), NULL, 16);
+    }
+    return version;
+}
 
-    std::vector<char> extractErrorBuffer;
-    DeployAgentFileCallback cb(outputFp, &extractErrorBuffer);
-    int returnCode = send_shell_command(extractCommand, false, &cb);
+static void update_agent_if_necessary() {
+    switch (g_agent_update_strategy) {
+        case FastDeploy_AgentUpdateAlways:
+            deploy_agent(/*check_time_stamps=*/false);
+            break;
+        case FastDeploy_AgentUpdateNewerTimeStamp:
+            deploy_agent(/*check_time_stamps=*/true);
+            break;
+        default:
+            break;
+    }
+}
+
+std::optional<APKMetaData> extract_metadata(const char* apk_path) {
+    // Update agent if there is a command line argument forcing to do so.
+    update_agent_if_necessary();
+
+    REPORT_FUNC_TIME();
+
+    std::string package_name = get_package_name_from_apk(apk_path);
+
+    // Dump apk command checks the required vs current agent version and if they match then returns
+    // the APK dump for package. Doing this in a single call saves round-trip and agent launch time.
+    constexpr const char* kAgentDumpCommandPattern = "/data/local/tmp/deployagent dump %ld %s";
+    std::string dump_command = android::base::StringPrintf(
+            kAgentDumpCommandPattern, kRequiredAgentVersion, package_name.c_str());
+
+    std::vector<char> dump_out_buffer;
+    std::vector<char> dump_error_buffer;
+    int returnCode =
+            capture_shell_command(dump_command.c_str(), &dump_out_buffer, &dump_error_buffer);
+    if (returnCode >= kInvalidAgentVersion) {
+        // Agent has wrong version or missing.
+        long agent_version = parse_agent_version(dump_out_buffer);
+        if (agent_version < 0) {
+            printf("Could not detect agent on device, deploying\n");
+        } else {
+            printf("Device agent version is (%ld), (%ld) is required, re-deploying\n",
+                   agent_version, kRequiredAgentVersion);
+        }
+        deploy_agent(/*check_time_stamps=*/false);
+
+        // Retry with new agent.
+        dump_out_buffer.clear();
+        dump_error_buffer.clear();
+        returnCode =
+                capture_shell_command(dump_command.c_str(), &dump_out_buffer, &dump_error_buffer);
+    }
     if (returnCode != 0) {
-        fprintf(stderr, "Executing %s returned %d\n", extractCommand.c_str(), returnCode);
-        fprintf(stderr, "%*s\n", int(extractErrorBuffer.size()), extractErrorBuffer.data());
+        if (returnCode == kInvalidAgentVersion) {
+            long agent_version = parse_agent_version(dump_out_buffer);
+            error_exit(
+                    "After update agent version remains incorrect! Expected %ld but version is %ld",
+                    kRequiredAgentVersion, agent_version);
+        }
+        if (returnCode == kPackageMissing) {
+            fprintf(stderr, "Package %s not found, falling back to install\n",
+                    package_name.c_str());
+            return {};
+        }
+        fprintf(stderr, "Executing %s returned %d\n", dump_command.c_str(), returnCode);
+        fprintf(stderr, "%*s\n", int(dump_error_buffer.size()), dump_error_buffer.data());
         error_exit("Aborting");
     }
+
+    com::android::fastdeploy::APKDump dump;
+    if (!dump.ParseFromArray(dump_out_buffer.data(), dump_out_buffer.size())) {
+        fprintf(stderr, "Can't parse output of %s\n", dump_command.c_str());
+        error_exit("Aborting");
+    }
+
+    return PatchUtils::GetDeviceAPKMetaData(dump);
 }
 
-static std::string get_patch_generator_command() {
-    if (g_use_localagent) {
-        // This should never happen on a Windows machine
-        const char* host_out = getenv("ANDROID_HOST_OUT");
-        if (host_out == nullptr) {
-            error_exit(
-                    "Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT "
-                    "is not defined");
-        }
-        return android::base::StringPrintf("java -jar %s/framework/deploypatchgenerator.jar",
-                                           host_out);
-    }
+unique_fd install_patch(int argc, const char** argv) {
+    REPORT_FUNC_TIME();
+    constexpr char kAgentApplyServicePattern[] = "shell:/data/local/tmp/deployagent apply - -pm %s";
 
-    std::string adb_dir = android::base::GetExecutableDirectory();
-    if (adb_dir.empty()) {
-        error_exit("Could not locate deploypatchgenerator.jar");
-    }
-    return android::base::StringPrintf(R"(java -jar "%s/deploypatchgenerator.jar")",
-                                       adb_dir.c_str());
-}
-
-void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath) {
-    std::string generatePatchCommand = android::base::StringPrintf(
-            R"(%s "%s" "%s" > "%s")", get_patch_generator_command().c_str(), apkPath, metadataPath,
-            patchPath);
-    int returnCode = system(generatePatchCommand.c_str());
-    if (returnCode != 0) {
-        error_exit("Executing %s returned %d", generatePatchCommand.c_str(), returnCode);
-    }
-}
-
-std::string get_patch_path(const char* apkPath) {
-    std::string packageName = get_packagename_from_apk(apkPath);
-    std::string patchDevicePath =
-            android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
-    return patchDevicePath;
-}
-
-void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath) {
-    const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -o %s";
-    std::string packageName = get_packagename_from_apk(apkPath);
-    std::string patchDevicePath = get_patch_path(apkPath);
-
-    std::vector<const char*> srcs = {patchPath};
-    bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
-    if (!push_ok) {
-        error_exit("Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
-    }
-
-    std::string applyPatchCommand =
-            android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
-                                        patchDevicePath.c_str(), outputPath);
-
-    int returnCode = send_shell_command(applyPatchCommand);
-    if (returnCode != 0) {
-        error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
-    }
-}
-
-void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv) {
-    const std::string kAgentApplyCommandPattern = "/data/local/tmp/deployagent apply %s %s -pm %s";
-    std::string packageName = get_packagename_from_apk(apkPath);
-
-    std::string patchDevicePath =
-            android::base::StringPrintf("%s%s.patch", kDeviceAgentPath, packageName.c_str());
-
-    std::vector<const char*> srcs{patchPath};
-    bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
-    if (!push_ok) {
-        error_exit("Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
-    }
-
-    std::vector<unsigned char> applyOutputBuffer;
-    std::vector<unsigned char> applyErrorBuffer;
+    std::vector<unsigned char> apply_output_buffer;
+    std::vector<unsigned char> apply_error_buffer;
     std::string argsString;
 
     bool rSwitchPresent = false;
@@ -326,17 +312,42 @@
         argsString.append("-r");
     }
 
-    std::string applyPatchCommand =
-            android::base::StringPrintf(kAgentApplyCommandPattern.c_str(), packageName.c_str(),
-                                        patchDevicePath.c_str(), argsString.c_str());
-    int returnCode = send_shell_command(applyPatchCommand);
-    if (returnCode != 0) {
-        error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
+    std::string error;
+    std::string apply_patch_service_string =
+            android::base::StringPrintf(kAgentApplyServicePattern, argsString.c_str());
+    unique_fd fd{adb_connect(apply_patch_service_string, &error)};
+    if (fd < 0) {
+        error_exit("Executing %s returned %s", apply_patch_service_string.c_str(), error.c_str());
+    }
+    return fd;
+}
+
+unique_fd apply_patch_on_device(const char* output_path) {
+    REPORT_FUNC_TIME();
+    constexpr char kAgentApplyServicePattern[] = "shell:/data/local/tmp/deployagent apply - -o %s";
+
+    std::string error;
+    std::string apply_patch_service_string =
+            android::base::StringPrintf(kAgentApplyServicePattern, output_path);
+    unique_fd fd{adb_connect(apply_patch_service_string, &error)};
+    if (fd < 0) {
+        error_exit("Executing %s returned %s", apply_patch_service_string.c_str(), error.c_str());
+    }
+    return fd;
+}
+
+static void create_patch(const char* apk_path, APKMetaData metadata, borrowed_fd patch_fd) {
+    REPORT_FUNC_TIME();
+    DeployPatchGenerator generator(/*is_verbose=*/false);
+    bool success = generator.CreatePatch(apk_path, std::move(metadata), patch_fd);
+    if (!success) {
+        error_exit("Failed to create patch for %s", apk_path);
     }
 }
 
-bool find_package(const char* apkPath) {
-    const std::string findCommand =
-            "/data/local/tmp/deployagent find " + get_packagename_from_apk(apkPath);
-    return !send_shell_command(findCommand);
+int stream_patch(const char* apk_path, APKMetaData metadata, unique_fd patch_fd) {
+    create_patch(apk_path, std::move(metadata), patch_fd);
+
+    REPORT_FUNC_TIME();
+    return read_and_dump(patch_fd.get());
 }
diff --git a/adb/client/fastdeploy.h b/adb/client/fastdeploy.h
index 7b7f2ec..830aeb2 100644
--- a/adb/client/fastdeploy.h
+++ b/adb/client/fastdeploy.h
@@ -16,6 +16,11 @@
 
 #pragma once
 
+#include "adb_unique_fd.h"
+
+#include "fastdeploy/proto/ApkEntry.pb.h"
+
+#include <optional>
 #include <string>
 
 enum FastDeploy_AgentUpdateStrategy {
@@ -24,12 +29,11 @@
     FastDeploy_AgentUpdateDifferentVersion
 };
 
-void fastdeploy_set_local_agent(bool use_localagent);
+void fastdeploy_set_agent_update_strategy(FastDeploy_AgentUpdateStrategy agent_update_strategy);
 int get_device_api_level();
-void update_agent(FastDeploy_AgentUpdateStrategy agentUpdateStrategy);
-void extract_metadata(const char* apkPath, FILE* outputFp);
-void create_patch(const char* apkPath, const char* metadataPath, const char* patchPath);
-void apply_patch_on_device(const char* apkPath, const char* patchPath, const char* outputPath);
-void install_patch(const char* apkPath, const char* patchPath, int argc, const char** argv);
-std::string get_patch_path(const char* apkPath);
-bool find_package(const char* apkPath);
+
+std::optional<com::android::fastdeploy::APKMetaData> extract_metadata(const char* apk_path);
+unique_fd install_patch(int argc, const char** argv);
+unique_fd apply_patch_on_device(const char* output_path);
+int stream_patch(const char* apk_path, com::android::fastdeploy::APKMetaData metadata,
+                 unique_fd patch_fd);
diff --git a/adb/client/fastdeploycallbacks.cpp b/adb/client/fastdeploycallbacks.cpp
index 23a0aca..86ceaa1 100644
--- a/adb/client/fastdeploycallbacks.cpp
+++ b/adb/client/fastdeploycallbacks.cpp
@@ -49,35 +49,7 @@
 int capture_shell_command(const char* command, std::vector<char>* outBuffer,
                           std::vector<char>* errBuffer) {
     DeployAgentBufferCallback cb(outBuffer, errBuffer);
-    return send_shell_command(command, false, &cb);
-}
-
-DeployAgentFileCallback::DeployAgentFileCallback(FILE* outputFile, std::vector<char>* errBuffer) {
-    mpOutFile = outputFile;
-    mpErrBuffer = errBuffer;
-    mBytesWritten = 0;
-}
-
-void DeployAgentFileCallback::OnStdout(const char* buffer, int length) {
-    if (mpOutFile != NULL) {
-        int bytes_written = fwrite(buffer, 1, length, mpOutFile);
-        if (bytes_written != length) {
-            printf("Write error %d\n", bytes_written);
-        }
-        mBytesWritten += bytes_written;
-    }
-}
-
-void DeployAgentFileCallback::OnStderr(const char* buffer, int length) {
-    appendBuffer(mpErrBuffer, buffer, length);
-}
-
-int DeployAgentFileCallback::Done(int status) {
-    return status;
-}
-
-int DeployAgentFileCallback::getBytesWritten() {
-    return mBytesWritten;
+    return send_shell_command(command, /*disable_shell_protocol=*/false, &cb);
 }
 
 DeployAgentBufferCallback::DeployAgentBufferCallback(std::vector<char>* outBuffer,
diff --git a/adb/client/fastdeploycallbacks.h b/adb/client/fastdeploycallbacks.h
index 7e049c5..4a6fb99 100644
--- a/adb/client/fastdeploycallbacks.h
+++ b/adb/client/fastdeploycallbacks.h
@@ -17,23 +17,6 @@
 #pragma once
 
 #include <vector>
-#include "commandline.h"
-
-class DeployAgentFileCallback : public StandardStreamsCallbackInterface {
-  public:
-    DeployAgentFileCallback(FILE* outputFile, std::vector<char>* errBuffer);
-
-    virtual void OnStdout(const char* buffer, int length);
-    virtual void OnStderr(const char* buffer, int length);
-    virtual int Done(int status);
-
-    int getBytesWritten();
-
-  private:
-    FILE* mpOutFile;
-    std::vector<char>* mpErrBuffer;
-    int mBytesWritten;
-};
 
 int capture_shell_command(const char* command, std::vector<char>* outBuffer,
                           std::vector<char>* errBuffer);
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 5d10238..fbfeb53 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -52,6 +52,8 @@
 #include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 
+typedef void(sync_ls_cb)(unsigned mode, uint64_t size, uint64_t time, const char* name);
+
 struct syncsendbuf {
     unsigned id;
     unsigned size;
@@ -210,6 +212,7 @@
             Error("failed to get feature set: %s", error.c_str());
         } else {
             have_stat_v2_ = CanUseFeature(features_, kFeatureStat2);
+            have_ls_v2_ = CanUseFeature(features_, kFeatureLs2);
             fd.reset(adb_connect("sync:", &error));
             if (fd < 0) {
                 Error("connect failed: %s", error.c_str());
@@ -357,7 +360,7 @@
                             << msg.stat_v1.id;
             }
 
-            if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.time == 0) {
+            if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.mtime == 0) {
                 // There's no way for us to know what the error was.
                 errno = ENOPROTOOPT;
                 return false;
@@ -365,13 +368,52 @@
 
             st->st_mode = msg.stat_v1.mode;
             st->st_size = msg.stat_v1.size;
-            st->st_ctime = msg.stat_v1.time;
-            st->st_mtime = msg.stat_v1.time;
+            st->st_ctime = msg.stat_v1.mtime;
+            st->st_mtime = msg.stat_v1.mtime;
         }
 
         return true;
     }
 
+    bool SendLs(const char* path) {
+        return SendRequest(have_ls_v2_ ? ID_LIST_V2 : ID_LIST_V1, path);
+    }
+
+  private:
+    template <bool v2>
+    static bool FinishLsImpl(borrowed_fd fd, const std::function<sync_ls_cb>& callback) {
+        using dent_type =
+                std::conditional_t<v2, decltype(syncmsg::dent_v2), decltype(syncmsg::dent_v1)>;
+
+        while (true) {
+            dent_type dent;
+            if (!ReadFdExactly(fd, &dent, sizeof(dent))) return false;
+
+            uint32_t expected_id = v2 ? ID_DENT_V2 : ID_DENT_V1;
+            if (dent.id == ID_DONE) return true;
+            if (dent.id != expected_id) return false;
+
+            // Maximum length of a file name excluding null terminator (NAME_MAX) on Linux is 255.
+            char buf[256];
+            size_t len = dent.namelen;
+            if (len > 255) return false;
+
+            if (!ReadFdExactly(fd, buf, len)) return false;
+            buf[len] = 0;
+
+            callback(dent.mode, dent.size, dent.mtime, buf);
+        }
+    }
+
+  public:
+    bool FinishLs(const std::function<sync_ls_cb>& callback) {
+        if (have_ls_v2_) {
+            return FinishLsImpl<true>(this->fd, callback);
+        } else {
+            return FinishLsImpl<false>(this->fd, callback);
+        }
+    }
+
     // Sending header, payload, and footer in a single write makes a huge
     // difference to "adb sync" performance.
     bool SendSmallFile(const char* path_and_mode,
@@ -578,6 +620,7 @@
     bool expect_done_;
     FeatureSet features_;
     bool have_stat_v2_;
+    bool have_ls_v2_;
 
     TransferLedger global_ledger_;
     TransferLedger current_ledger_;
@@ -609,28 +652,9 @@
     }
 };
 
-typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
-
 static bool sync_ls(SyncConnection& sc, const char* path,
                     const std::function<sync_ls_cb>& func) {
-    if (!sc.SendRequest(ID_LIST, path)) return false;
-
-    while (true) {
-        syncmsg msg;
-        if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false;
-
-        if (msg.dent.id == ID_DONE) return true;
-        if (msg.dent.id != ID_DENT) return false;
-
-        size_t len = msg.dent.namelen;
-        if (len > 256) return false; // TODO: resize buffer? continue?
-
-        char buf[257];
-        if (!ReadFdExactly(sc.fd, buf, len)) return false;
-        buf[len] = 0;
-
-        func(msg.dent.mode, msg.dent.size, msg.dent.time, buf);
-    }
+    return sc.SendLs(path) && sc.FinishLs(func);
 }
 
 static bool sync_stat(SyncConnection& sc, const char* path, struct stat* st) {
@@ -787,9 +811,8 @@
     SyncConnection sc;
     if (!sc.IsValid()) return false;
 
-    return sync_ls(sc, path, [](unsigned mode, unsigned size, unsigned time,
-                                const char* name) {
-        printf("%08x %08x %08x %s\n", mode, size, time, name);
+    return sync_ls(sc, path, [](unsigned mode, uint64_t size, uint64_t time, const char* name) {
+        printf("%08x %08" PRIx64 " %08" PRIx64 " %s\n", mode, size, time, name);
     });
 }
 
@@ -849,6 +872,16 @@
     return true;
 }
 
+// dirname("//foo") returns "//", so we can't do the obvious `path == "/"`.
+static bool is_root_dir(std::string_view path) {
+    for (char c : path) {
+        if (c != '/') {
+            return false;
+        }
+    }
+    return true;
+}
+
 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
                                   std::string rpath, bool check_timestamps,
                                   bool list_only) {
@@ -862,8 +895,8 @@
     std::vector<copyinfo> file_list;
     std::vector<std::string> directory_list;
 
-    for (std::string dirpath = rpath; dirpath != "/"; dirpath = android::base::Dirname(dirpath)) {
-        directory_list.push_back(dirpath);
+    for (std::string path = rpath; !is_root_dir(path); path = android::base::Dirname(path)) {
+        directory_list.push_back(path);
     }
     std::reverse(directory_list.begin(), directory_list.end());
 
@@ -1052,7 +1085,7 @@
     file_list->push_back(ci);
 
     // Put the files/dirs in rpath on the lists.
-    auto callback = [&](unsigned mode, unsigned size, unsigned time, const char* name) {
+    auto callback = [&](unsigned mode, uint64_t size, uint64_t time, const char* name) {
         if (IsDotOrDotDot(name)) {
             return;
         }
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 0c5c28f..e5ffe4c 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -129,7 +129,7 @@
     }
 
     if (!getenv("ADB_EMU") || strcmp(getenv("ADB_EMU"), "0") != 0) {
-        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+        local_init(android::base::StringPrintf("tcp:%d", DEFAULT_ADB_LOCAL_TRANSPORT_PORT));
     }
 
     std::string error;
diff --git a/adb/client/transport_mdns.cpp b/adb/client/transport_mdns.cpp
index 283fac5..1a34384 100644
--- a/adb/client/transport_mdns.cpp
+++ b/adb/client/transport_mdns.cpp
@@ -31,7 +31,7 @@
 
 #include "adb_mdns.h"
 #include "adb_trace.h"
-#include "fdevent.h"
+#include "fdevent/fdevent.h"
 #include "sysdeps.h"
 
 static DNSServiceRef service_ref;
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index 81b8306..343e7b5 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -324,7 +324,7 @@
 
     h->urb_out_busy = true;
     while (true) {
-        auto now = std::chrono::system_clock::now();
+        auto now = std::chrono::steady_clock::now();
         if (h->cv.wait_until(lock, now + 5s) == std::cv_status::timeout || h->dead) {
             // TODO: call USBDEVFS_DISCARDURB?
             errno = ETIMEDOUT;
@@ -406,25 +406,44 @@
     }
 }
 
-int usb_write(usb_handle *h, const void *_data, int len)
-{
+static int usb_write_split(usb_handle* h, unsigned char* data, int len) {
+    for (int i = 0; i < len; i += 16384) {
+        int chunk_size = (i + 16384 > len) ? len - i : 16384;
+        int n = usb_bulk_write(h, data + i, chunk_size);
+        if (n != chunk_size) {
+            D("ERROR: n = %d, errno = %d (%s)", n, errno, strerror(errno));
+            return -1;
+        }
+    }
+
+    return len;
+}
+
+int usb_write(usb_handle* h, const void* _data, int len) {
     D("++ usb_write ++");
 
-    unsigned char *data = (unsigned char*) _data;
+    unsigned char* data = (unsigned char*)_data;
+
+    // The kernel will attempt to allocate a contiguous buffer for each write we submit.
+    // This might fail due to heap fragmentation, so attempt a contiguous write once, and if that
+    // fails, retry after having split the data into 16kB chunks to avoid allocation failure.
     int n = usb_bulk_write(h, data, len);
-    if (n != len) {
-        D("ERROR: n = %d, errno = %d (%s)", n, errno, strerror(errno));
+    if (n == -1 && errno == ENOMEM) {
+        n = usb_write_split(h, data, len);
+    }
+
+    if (n == -1) {
         return -1;
     }
 
     if (h->zero_mask && !(len & h->zero_mask)) {
         // If we need 0-markers and our transfer is an even multiple of the packet size,
         // then send a zero marker.
-        return usb_bulk_write(h, _data, 0) == 0 ? n : -1;
+        return usb_bulk_write(h, _data, 0) == 0 ? len : -1;
     }
 
     D("-- usb_write --");
-    return n;
+    return len;
 }
 
 int usb_read(usb_handle *h, void *_data, int len)
@@ -590,6 +609,7 @@
     while (true) {
         // TODO: Use inotify.
         find_usb_device("/dev/bus/usb", register_device);
+        adb_notify_device_scan_complete();
         kick_disconnected_devices();
         std::this_thread::sleep_for(1s);
     }
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index 5c0da47..7207ca7 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -461,6 +461,7 @@
             std::this_thread::sleep_for(100ms);
         }
 
+        adb_notify_device_scan_complete();
         initialized = true;
     }
 }
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index f23c3a5..197c6fa 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -172,6 +172,7 @@
 
     while (true) {
         find_devices();
+        adb_notify_device_scan_complete();
         std::this_thread::sleep_for(1s);
     }
 }
diff --git a/adb/daemon/abb.cpp b/adb/daemon/abb.cpp
index eeac41a..17c25e8 100644
--- a/adb/daemon/abb.cpp
+++ b/adb/daemon/abb.cpp
@@ -17,22 +17,24 @@
 #include <sys/wait.h>
 
 #include <android-base/cmsg.h>
+#include <android-base/strings.h>
 #include <cmd.h>
 
 #include "adb.h"
 #include "adb_io.h"
 #include "adb_utils.h"
 #include "shell_service.h"
+#include "sysdeps.h"
 
 namespace {
 
 class AdbFdTextOutput : public android::TextOutput {
   public:
-    explicit AdbFdTextOutput(int fd) : mFD(fd) {}
+    explicit AdbFdTextOutput(borrowed_fd fd) : fd_(fd) {}
 
   private:
     android::status_t print(const char* txt, size_t len) override {
-        return WriteFdExactly(mFD, txt, len) ? android::OK : -errno;
+        return WriteFdExactly(fd_, txt, len) ? android::OK : -errno;
     }
     void moveIndent(int delta) override { /*not implemented*/
     }
@@ -43,7 +45,7 @@
     }
 
   private:
-    int mFD;
+    borrowed_fd fd_;
 };
 
 std::vector<std::string_view> parseCmdArgs(std::string_view args) {
@@ -67,10 +69,16 @@
 
 }  // namespace
 
-static int execCmd(std::string_view args, int in, int out, int err) {
+static int execCmd(std::string_view args, borrowed_fd in, borrowed_fd out, borrowed_fd err) {
+    int max_buf = LINUX_MAX_SOCKET_SIZE;
+    adb_setsockopt(in, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
+    adb_setsockopt(out, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
+    adb_setsockopt(err, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
+
     AdbFdTextOutput oin(out);
     AdbFdTextOutput oerr(err);
-    return cmdMain(parseCmdArgs(args), oin, oerr, in, out, err, RunMode::kLibrary);
+    return cmdMain(parseCmdArgs(args), oin, oerr, in.get(), out.get(), err.get(),
+                   RunMode::kLibrary);
 }
 
 int main(int argc, char* const argv[]) {
@@ -87,15 +95,17 @@
 
         std::string_view name = data;
         auto protocol = SubprocessProtocol::kShell;
-        if (ConsumePrefix(&name, "abb:")) {
+        if (android::base::ConsumePrefix(&name, "abb:")) {
             protocol = SubprocessProtocol::kShell;
-        } else if (ConsumePrefix(&name, "abb_exec:")) {
+        } else if (android::base::ConsumePrefix(&name, "abb_exec:")) {
             protocol = SubprocessProtocol::kNone;
         } else {
             LOG(FATAL) << "Unknown command prefix for abb: " << data;
         }
 
         unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol);
+        int max_buf = LINUX_MAX_SOCKET_SIZE;
+        adb_setsockopt(result, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
         if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) {
             PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data;
             break;
diff --git a/adb/daemon/abb_service.cpp b/adb/daemon/abb_service.cpp
index a435279..e1df4a5 100644
--- a/adb/daemon/abb_service.cpp
+++ b/adb/daemon/abb_service.cpp
@@ -53,14 +53,13 @@
             return error_fd;
         }
 
-        if (!SendProtocolString(socket_fd_, std::string(command))) {
+        if (!SendProtocolString(socket_fd_, command)) {
             PLOG(ERROR) << "failed to send command to abb";
             socket_fd_.reset();
             continue;
         }
 
         unique_fd fd;
-        std::string error;
         char buf;
         if (android::base::ReceiveFileDescriptors(socket_fd_, &buf, 1, &fd) != 1) {
             PLOG(ERROR) << "failed to receive FD from abb";
diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp
index a18afa4..ec4ab4a 100644
--- a/adb/daemon/auth.cpp
+++ b/adb/daemon/auth.cpp
@@ -16,107 +16,116 @@
 
 #define TRACE_TAG AUTH
 
-#include "adb.h"
-#include "adb_auth.h"
-#include "adb_io.h"
-#include "fdevent.h"
 #include "sysdeps.h"
-#include "transport.h"
 
 #include <resolv.h>
 #include <stdio.h>
 #include <string.h>
-#include <iomanip>
 
 #include <algorithm>
+#include <iomanip>
+#include <map>
 #include <memory>
 
+#include <adbd_auth.h>
 #include <android-base/file.h>
+#include <android-base/no_destructor.h>
 #include <android-base/strings.h>
 #include <crypto_utils/android_pubkey.h>
 #include <openssl/obj_mac.h>
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 
-static fdevent* listener_fde = nullptr;
-static fdevent* framework_fde = nullptr;
-static auto& framework_mutex = *new std::mutex();
-static int framework_fd GUARDED_BY(framework_mutex) = -1;
-static auto& connected_keys GUARDED_BY(framework_mutex) = *new std::vector<std::string>;
+#include "adb.h"
+#include "adb_auth.h"
+#include "adb_io.h"
+#include "fdevent/fdevent.h"
+#include "transport.h"
+#include "types.h"
+
+static AdbdAuthContext* auth_ctx;
 
 static void adb_disconnected(void* unused, atransport* t);
 static struct adisconnect adb_disconnect = {adb_disconnected, nullptr};
-static atransport* adb_transport;
-static bool needs_retry = false;
+
+static android::base::NoDestructor<std::map<uint32_t, weak_ptr<atransport>>> transports;
+static uint32_t transport_auth_id = 0;
 
 bool auth_required = true;
 
-bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig,
-                      std::string* auth_key) {
-    static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
-
-    for (const auto& path : key_paths) {
-        if (access(path, R_OK) == 0) {
-            LOG(INFO) << "Loading keys from " << path;
-            std::string content;
-            if (!android::base::ReadFileToString(path, &content)) {
-                PLOG(ERROR) << "Couldn't read " << path;
-                continue;
-            }
-
-            for (const auto& line : android::base::Split(content, "\n")) {
-                if (line.empty()) continue;
-                *auth_key = line;
-                // TODO: do we really have to support both ' ' and '\t'?
-                char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
-                if (sep) *sep = '\0';
-
-                // b64_pton requires one additional byte in the target buffer for
-                // decoding to succeed. See http://b/28035006 for details.
-                uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
-                if (b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
-                    LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
-                    continue;
-                }
-
-                RSA* key = nullptr;
-                if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
-                    LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path;
-                    continue;
-                }
-
-                bool verified =
-                    (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
-                                reinterpret_cast<const uint8_t*>(sig.c_str()), sig.size(),
-                                key) == 1);
-                RSA_free(key);
-                if (verified) return true;
-            }
-        }
-    }
-    auth_key->clear();
-    return false;
+static void* transport_to_callback_arg(atransport* transport) {
+    uint32_t id = transport_auth_id++;
+    (*transports)[id] = transport->weak();
+    return reinterpret_cast<void*>(id);
 }
 
-static bool adbd_send_key_message_locked(std::string_view msg_type, std::string_view key)
-        REQUIRES(framework_mutex) {
-    if (framework_fd < 0) {
-        LOG(ERROR) << "Client not connected to send msg_type " << msg_type;
-        return false;
-    }
-    std::string msg = std::string(msg_type) + std::string(key);
-    int msg_len = msg.length();
-    if (msg_len >= static_cast<int>(MAX_FRAMEWORK_PAYLOAD)) {
-        LOG(ERROR) << "Key too long (" << msg_len << ")";
-        return false;
+static atransport* transport_from_callback_arg(void* id) {
+    uint64_t id_u64 = reinterpret_cast<uint64_t>(id);
+    if (id_u64 > std::numeric_limits<uint32_t>::max()) {
+        LOG(FATAL) << "transport_from_callback_arg called on out of range value: " << id_u64;
     }
 
-    LOG(DEBUG) << "Sending '" << msg << "'";
-    if (!WriteFdExactly(framework_fd, msg.c_str(), msg_len)) {
-        PLOG(ERROR) << "Failed to write " << msg_type;
-        return false;
+    uint32_t id_u32 = static_cast<uint32_t>(id_u64);
+    auto it = transports->find(id_u32);
+    if (it == transports->end()) {
+        LOG(ERROR) << "transport_from_callback_arg failed to find transport for id " << id_u32;
+        return nullptr;
     }
-    return true;
+
+    atransport* t = it->second.get();
+    if (!t) {
+        LOG(WARNING) << "transport_from_callback_arg found already destructed transport";
+        return nullptr;
+    }
+
+    transports->erase(it);
+    return t;
+}
+
+static void IteratePublicKeys(std::function<bool(std::string_view public_key)> f) {
+    adbd_auth_get_public_keys(
+            auth_ctx,
+            [](const char* public_key, size_t len, void* arg) {
+                return (*static_cast<decltype(f)*>(arg))(std::string_view(public_key, len));
+            },
+            &f);
+}
+
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig,
+                      std::string* auth_key) {
+    bool authorized = false;
+    auth_key->clear();
+
+    IteratePublicKeys([&](std::string_view public_key) {
+        // TODO: do we really have to support both ' ' and '\t'?
+        std::vector<std::string> split = android::base::Split(std::string(public_key), " \t");
+        uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
+        const std::string& pubkey = split[0];
+        if (b64_pton(pubkey.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
+            LOG(ERROR) << "Invalid base64 key " << pubkey;
+            return true;
+        }
+
+        RSA* key = nullptr;
+        if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
+            LOG(ERROR) << "Failed to parse key " << pubkey;
+            return true;
+        }
+
+        bool verified =
+                (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
+                            reinterpret_cast<const uint8_t*>(sig.c_str()), sig.size(), key) == 1);
+        RSA_free(key);
+        if (verified) {
+            *auth_key = public_key;
+            authorized = true;
+            return false;
+        }
+
+        return true;
+    });
+
+    return authorized;
 }
 
 static bool adbd_auth_generate_token(void* token, size_t token_size) {
@@ -127,113 +136,6 @@
     return okay;
 }
 
-static void adb_disconnected(void* unused, atransport* t) {
-    LOG(INFO) << "ADB disconnect";
-    adb_transport = nullptr;
-    needs_retry = false;
-    {
-        std::lock_guard<std::mutex> lock(framework_mutex);
-        if (framework_fd >= 0) {
-            adbd_send_key_message_locked("DC", t->auth_key);
-        }
-        connected_keys.erase(std::remove(connected_keys.begin(), connected_keys.end(), t->auth_key),
-                             connected_keys.end());
-    }
-}
-
-static void framework_disconnected() {
-    LOG(INFO) << "Framework disconnect";
-    if (framework_fde) {
-        fdevent_destroy(framework_fde);
-        {
-            std::lock_guard<std::mutex> lock(framework_mutex);
-            framework_fd = -1;
-        }
-    }
-}
-
-static void adbd_auth_event(int fd, unsigned events, void*) {
-    if (events & FDE_READ) {
-        char response[2];
-        int ret = unix_read(fd, response, sizeof(response));
-        if (ret <= 0) {
-            framework_disconnected();
-        } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
-            if (adb_transport) {
-                adbd_auth_verified(adb_transport);
-            }
-        }
-    }
-}
-
-void adbd_auth_confirm_key(atransport* t) {
-    if (!adb_transport) {
-        adb_transport = t;
-        t->AddDisconnect(&adb_disconnect);
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(framework_mutex);
-        if (framework_fd < 0) {
-            LOG(ERROR) << "Client not connected";
-            needs_retry = true;
-            return;
-        }
-
-        adbd_send_key_message_locked("PK", t->auth_key);
-    }
-}
-
-static void adbd_auth_listener(int fd, unsigned events, void* data) {
-    int s = adb_socket_accept(fd, nullptr, nullptr);
-    if (s < 0) {
-        PLOG(ERROR) << "Failed to accept";
-        return;
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(framework_mutex);
-        if (framework_fd >= 0) {
-            LOG(WARNING) << "adb received framework auth socket connection again";
-            framework_disconnected();
-        }
-
-        framework_fd = s;
-        framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr);
-        fdevent_add(framework_fde, FDE_READ);
-
-        if (needs_retry) {
-            needs_retry = false;
-            send_auth_request(adb_transport);
-        }
-
-        // if a client connected before the framework was available notify the framework of the
-        // connected key now.
-        if (!connected_keys.empty()) {
-            for (const auto& key : connected_keys) {
-                adbd_send_key_message_locked("CK", key);
-            }
-        }
-    }
-}
-
-void adbd_notify_framework_connected_key(atransport* t) {
-    if (!adb_transport) {
-        adb_transport = t;
-        t->AddDisconnect(&adb_disconnect);
-    }
-    {
-        std::lock_guard<std::mutex> lock(framework_mutex);
-        if (std::find(connected_keys.begin(), connected_keys.end(), t->auth_key) ==
-            connected_keys.end()) {
-            connected_keys.push_back(t->auth_key);
-        }
-        if (framework_fd >= 0) {
-            adbd_send_key_message_locked("CK", t->auth_key);
-        }
-    }
-}
-
 void adbd_cloexec_auth_socket() {
     int fd = android_get_control_socket("adbd");
     if (fd == -1) {
@@ -243,20 +145,30 @@
     fcntl(fd, F_SETFD, FD_CLOEXEC);
 }
 
+static void adbd_auth_key_authorized(void* arg, uint64_t id) {
+    LOG(INFO) << "adb client authorized";
+    fdevent_run_on_main_thread([=]() {
+        LOG(INFO) << "arg = " << reinterpret_cast<uintptr_t>(arg);
+        auto* transport = transport_from_callback_arg(arg);
+        if (!transport) {
+            LOG(ERROR) << "authorization received for deleted transport, ignoring";
+            return;
+        }
+        transport->auth_id = id;
+        adbd_auth_verified(transport);
+    });
+}
+
 void adbd_auth_init(void) {
-    int fd = android_get_control_socket("adbd");
-    if (fd == -1) {
-        PLOG(ERROR) << "Failed to get adbd socket";
-        return;
-    }
-
-    if (listen(fd, 4) == -1) {
-        PLOG(ERROR) << "Failed to listen on '" << fd << "'";
-        return;
-    }
-
-    listener_fde = fdevent_create(fd, adbd_auth_listener, nullptr);
-    fdevent_add(listener_fde, FDE_READ);
+    AdbdAuthCallbacks cb;
+    cb.version = 1;
+    cb.callbacks.v1.key_authorized = adbd_auth_key_authorized;
+    auth_ctx = adbd_auth_new(&cb);
+    std::thread([]() {
+        adb_thread_setname("adbd auth");
+        adbd_auth_run(auth_ctx);
+        LOG(FATAL) << "auth thread terminated";
+    }).detach();
 }
 
 void send_auth_request(atransport* t) {
@@ -280,3 +192,19 @@
     handle_online(t);
     send_connect(t);
 }
+
+static void adb_disconnected(void* unused, atransport* t) {
+    LOG(INFO) << "ADB disconnect";
+    adbd_auth_notify_disconnect(auth_ctx, t->auth_id);
+}
+
+void adbd_auth_confirm_key(atransport* t) {
+    LOG(INFO) << "prompting user to authorize key";
+    t->AddDisconnect(&adb_disconnect);
+    adbd_auth_prompt_user(auth_ctx, t->auth_key.data(), t->auth_key.size(),
+                          transport_to_callback_arg(t));
+}
+
+void adbd_notify_framework_connected_key(atransport* t) {
+    adbd_auth_notify_auth(auth_ctx, t->auth_key.data(), t->auth_key.size());
+}
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index e82a51f..d6af708 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -139,7 +139,7 @@
     lstat(path, &st);
     msg.stat_v1.mode = st.st_mode;
     msg.stat_v1.size = st.st_size;
-    msg.stat_v1.time = st.st_mtime;
+    msg.stat_v1.mtime = st.st_mtime;
     return WriteFdExactly(s, &msg.stat_v1, sizeof(msg.stat_v1));
 }
 
@@ -174,40 +174,73 @@
     return WriteFdExactly(s, &msg.stat_v2, sizeof(msg.stat_v2));
 }
 
+template <bool v2>
 static bool do_list(int s, const char* path) {
     dirent* de;
 
-    syncmsg msg;
-    msg.dent.id = ID_DENT;
+    using MessageType =
+            std::conditional_t<v2, decltype(syncmsg::dent_v2), decltype(syncmsg::dent_v1)>;
+    MessageType msg;
+    uint32_t msg_id;
+    if constexpr (v2) {
+        msg_id = ID_DENT_V2;
+    } else {
+        msg_id = ID_DENT_V1;
+    }
 
     std::unique_ptr<DIR, int(*)(DIR*)> d(opendir(path), closedir);
     if (!d) goto done;
 
     while ((de = readdir(d.get()))) {
+        memset(&msg, 0, sizeof(msg));
+        msg.id = msg_id;
+
         std::string filename(StringPrintf("%s/%s", path, de->d_name));
 
         struct stat st;
         if (lstat(filename.c_str(), &st) == 0) {
-            size_t d_name_length = strlen(de->d_name);
-            msg.dent.mode = st.st_mode;
-            msg.dent.size = st.st_size;
-            msg.dent.time = st.st_mtime;
-            msg.dent.namelen = d_name_length;
+            msg.mode = st.st_mode;
+            msg.size = st.st_size;
+            msg.mtime = st.st_mtime;
 
-            if (!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
-                    !WriteFdExactly(s, de->d_name, d_name_length)) {
-                return false;
+            if constexpr (v2) {
+                msg.dev = st.st_dev;
+                msg.ino = st.st_ino;
+                msg.nlink = st.st_nlink;
+                msg.uid = st.st_uid;
+                msg.gid = st.st_gid;
+                msg.atime = st.st_atime;
+                msg.ctime = st.st_ctime;
             }
+        } else {
+            if constexpr (v2) {
+                msg.error = errno;
+            } else {
+                continue;
+            }
+        }
+
+        size_t d_name_length = strlen(de->d_name);
+        msg.namelen = d_name_length;
+
+        if (!WriteFdExactly(s, &msg, sizeof(msg)) ||
+            !WriteFdExactly(s, de->d_name, d_name_length)) {
+            return false;
         }
     }
 
 done:
-    msg.dent.id = ID_DONE;
-    msg.dent.mode = 0;
-    msg.dent.size = 0;
-    msg.dent.time = 0;
-    msg.dent.namelen = 0;
-    return WriteFdExactly(s, &msg.dent, sizeof(msg.dent));
+    memset(&msg, 0, sizeof(msg));
+    msg.id = ID_DONE;
+    return WriteFdExactly(s, &msg, sizeof(msg));
+}
+
+static bool do_list_v1(int s, const char* path) {
+    return do_list<false>(s, path);
+}
+
+static bool do_list_v2(int s, const char* path) {
+    return do_list<true>(s, path);
 }
 
 // Make sure that SendFail from adb_io.cpp isn't accidentally used in this file.
@@ -229,17 +262,13 @@
 static bool handle_send_file(int s, const char* path, uint32_t* timestamp, uid_t uid, gid_t gid,
                              uint64_t capabilities, mode_t mode, std::vector<char>& buffer,
                              bool do_unlink) {
+    int rc;
     syncmsg msg;
 
     __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path);
 
     unique_fd fd(adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode));
 
-    if (posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED) <
-        0) {
-        D("[ Failed to fadvise: %d ]", errno);
-    }
-
     if (fd < 0 && errno == ENOENT) {
         if (!secure_mkdirs(Dirname(path))) {
             SendSyncFailErrno(s, "secure_mkdirs failed");
@@ -270,6 +299,12 @@
         fchmod(fd.get(), mode);
     }
 
+    rc = posix_fadvise(fd.get(), 0, 0,
+                       POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED);
+    if (rc != 0) {
+        D("[ Failed to fadvise: %s ]", strerror(rc));
+    }
+
     while (true) {
         if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
 
@@ -464,8 +499,9 @@
         return false;
     }
 
-    if (posix_fadvise(fd.get(), 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE) < 0) {
-        D("[ Failed to fadvise: %d ]", errno);
+    int rc = posix_fadvise(fd.get(), 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
+    if (rc != 0) {
+        D("[ Failed to fadvise: %s ]", strerror(rc));
     }
 
     syncmsg msg;
@@ -496,8 +532,10 @@
       return "lstat_v2";
     case ID_STAT_V2:
       return "stat_v2";
-    case ID_LIST:
-      return "list";
+    case ID_LIST_V1:
+      return "list_v1";
+    case ID_LIST_V2:
+      return "list_v2";
     case ID_SEND:
       return "send";
     case ID_RECV:
@@ -543,8 +581,11 @@
         case ID_STAT_V2:
             if (!do_stat_v2(fd, request.id, name)) return false;
             break;
-        case ID_LIST:
-            if (!do_list(fd, name)) return false;
+        case ID_LIST_V1:
+            if (!do_list_v1(fd, name)) return false;
+            break;
+        case ID_LIST_V2:
+            if (!do_list_v2(fd, name)) return false;
             break;
         case ID_SEND:
             if (!do_send(fd, name, buffer)) return false;
diff --git a/adb/daemon/framebuffer_service.cpp b/adb/daemon/framebuffer_service.cpp
index 2a6418a..676f8e9 100644
--- a/adb/daemon/framebuffer_service.cpp
+++ b/adb/daemon/framebuffer_service.cpp
@@ -33,7 +33,6 @@
 #include "adb.h"
 #include "adb_io.h"
 #include "adb_utils.h"
-#include "fdevent.h"
 
 /* TODO:
 ** - sync with vsync to avoid tearing
diff --git a/adb/daemon/include/adbd/usb.h b/adb/daemon/include/adbd/usb.h
index fca3c58..2204246 100644
--- a/adb/daemon/include/adbd/usb.h
+++ b/adb/daemon/include/adbd/usb.h
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <linux/usb/functionfs.h>
+
 #include <atomic>
 #include <condition_variable>
 #include <mutex>
diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index 66bfc0d..b92a7de 100644
--- a/adb/daemon/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -30,15 +30,21 @@
 
 #include <list>
 #include <memory>
+#include <thread>
 #include <vector>
 
+#include <adbconnection/server.h>
 #include <android-base/cmsg.h>
+#include <android-base/unique_fd.h>
 
 #include "adb.h"
 #include "adb_io.h"
 #include "adb_unique_fd.h"
 #include "adb_utils.h"
 
+using android::base::borrowed_fd;
+using android::base::unique_fd;
+
 /* here's how these things work.
 
    when adbd starts, it creates a unix server socket
@@ -133,16 +139,16 @@
 static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
 
 struct JdwpProcess {
-    explicit JdwpProcess(int socket) {
+    JdwpProcess(unique_fd socket, pid_t pid) {
+        CHECK(pid != 0);
+
         this->socket = socket;
-        this->fde = fdevent_create(socket, jdwp_process_event, this);
+        this->pid = pid;
+        this->fde = fdevent_create(socket.release(), jdwp_process_event, this);
 
         if (!this->fde) {
             LOG(FATAL) << "could not create fdevent for new JDWP process";
         }
-
-        /* start by waiting for the PID */
-        fdevent_add(this->fde, FDE_READ);
     }
 
     ~JdwpProcess() {
@@ -160,18 +166,12 @@
     }
 
     void RemoveFromList() {
-        if (this->pid >= 0) {
-            D("removing pid %d from jdwp process list", this->pid);
-        } else {
-            D("removing transient JdwpProcess from list");
-        }
-
         auto pred = [this](const auto& proc) { return proc.get() == this; };
         _jdwp_list.remove_if(pred);
     }
 
+    borrowed_fd socket = -1;
     int32_t pid = -1;
-    int socket = -1;
     fdevent* fde = nullptr;
 
     std::vector<unique_fd> out_fds;
@@ -181,11 +181,6 @@
     std::string temp;
 
     for (auto& proc : _jdwp_list) {
-        /* skip transient connections */
-        if (proc->pid < 0) {
-            continue;
-        }
-
         std::string next = std::to_string(proc->pid) + "\n";
         if (temp.length() + next.length() > bufferlen) {
             D("truncating JDWP process list (max len = %zu)", bufferlen);
@@ -214,24 +209,12 @@
 
 static void jdwp_process_event(int socket, unsigned events, void* _proc) {
     JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
-    CHECK_EQ(socket, proc->socket);
+    CHECK_EQ(socket, proc->socket.get());
 
     if (events & FDE_READ) {
-        if (proc->pid < 0) {
-            ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
-            if (rc != sizeof(proc->pid)) {
-                D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
-                goto CloseProcess;
-            }
-
-            /* all is well, keep reading to detect connection closure */
-            D("Adding pid %d to jdwp process list", proc->pid);
-            jdwp_process_list_updated();
-        } else {
-            // We already have the PID, if we can read from the socket, we've probably hit EOF.
-            D("terminating JDWP connection %d", proc->pid);
-            goto CloseProcess;
-        }
+        // We already have the PID, if we can read from the socket, we've probably hit EOF.
+        D("terminating JDWP connection %d", proc->pid);
+        goto CloseProcess;
     }
 
     if (events & FDE_WRITE) {
@@ -284,98 +267,6 @@
     return unique_fd{};
 }
 
-/**  VM DEBUG CONTROL SOCKET
- **
- **  we do implement a custom asocket to receive the data
- **/
-
-/* name of the debug control Unix socket */
-#define JDWP_CONTROL_NAME "\0jdwp-control"
-#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
-
-struct JdwpControl {
-    int listen_socket;
-    fdevent* fde;
-};
-
-static JdwpControl _jdwp_control;
-
-static void jdwp_control_event(int s, unsigned events, void* user);
-
-static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) {
-    sockaddr_un addr;
-    socklen_t addrlen;
-    int maxpath = sizeof(addr.sun_path);
-    int pathlen = socknamelen;
-
-    if (pathlen >= maxpath) {
-        D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath);
-        return -1;
-    }
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    memcpy(addr.sun_path, sockname, socknamelen);
-
-    unique_fd s(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
-    if (s < 0) {
-        D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
-        return -1;
-    }
-
-    addrlen = pathlen + sizeof(addr.sun_family);
-
-    if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
-        D("could not bind vm debug control socket: %d: %s", errno, strerror(errno));
-        return -1;
-    }
-
-    if (listen(s, 4) < 0) {
-        D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno));
-        return -1;
-    }
-
-    control->listen_socket = s.release();
-    control->fde = fdevent_create(control->listen_socket, jdwp_control_event, control);
-    if (control->fde == nullptr) {
-        D("could not create fdevent for jdwp control socket");
-        return -1;
-    }
-
-    /* only wait for incoming connections */
-    fdevent_add(control->fde, FDE_READ);
-
-    D("jdwp control socket started (%d)", control->listen_socket);
-    return 0;
-}
-
-static void jdwp_control_event(int fd, unsigned events, void* _control) {
-    JdwpControl* control = (JdwpControl*)_control;
-
-    CHECK_EQ(fd, control->listen_socket);
-    if (events & FDE_READ) {
-        int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
-        if (s < 0) {
-            if (errno == ECONNABORTED) {
-                /* oops, the JDWP process died really quick */
-                D("oops, the JDWP process died really quick");
-                return;
-            } else {
-                /* the socket is probably closed ? */
-                D("weird accept() failed on jdwp control socket: %s", strerror(errno));
-                return;
-            }
-        }
-
-        auto proc = std::make_unique<JdwpProcess>(s);
-        if (!proc) {
-            LOG(FATAL) << "failed to allocate JdwpProcess";
-        }
-
-        _jdwp_list.emplace_back(std::move(proc));
-    }
-}
-
 /** "jdwp" local service implementation
  ** this simply returns the list of known JDWP process pids
  **/
@@ -526,7 +417,22 @@
 }
 
 int init_jdwp(void) {
-    return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
+    std::thread([]() {
+        adb_thread_setname("jdwp control");
+        adbconnection_listen([](int fd, pid_t pid) {
+            LOG(INFO) << "jdwp connection from " << pid;
+            fdevent_run_on_main_thread([fd, pid] {
+                unique_fd ufd(fd);
+                auto proc = std::make_unique<JdwpProcess>(std::move(ufd), pid);
+                if (!proc) {
+                    LOG(FATAL) << "failed to allocate JdwpProcess";
+                }
+                _jdwp_list.emplace_back(std::move(proc));
+                jdwp_process_list_updated();
+            });
+        });
+    }).detach();
+    return 0;
 }
 
 #endif /* !ADB_HOST */
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index e5a4917..3322574 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -32,11 +32,13 @@
 #include <sys/prctl.h>
 
 #include <memory>
+#include <vector>
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 
 #if defined(__ANDROID__)
 #include <libminijail.h>
@@ -51,6 +53,7 @@
 #include "adb_auth.h"
 #include "adb_listeners.h"
 #include "adb_utils.h"
+#include "socket_spec.h"
 #include "transport.h"
 
 #include "mdns.h"
@@ -179,12 +182,26 @@
 }
 #endif
 
-static void setup_port(int port) {
-    LOG(INFO) << "adbd listening on port " << port;
-    local_init(port);
+static void setup_adb(const std::vector<std::string>& addrs) {
 #if defined(__ANDROID__)
+    // Get the first valid port from addrs and setup mDNS.
+    int port = -1;
+    std::string error;
+    for (const auto& addr : addrs) {
+        port = get_host_socket_spec_port(addr, &error);
+        if (port != -1) {
+            break;
+        }
+    }
+    if (port == -1) {
+        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    }
     setup_mdns(port);
 #endif
+    for (const auto& addr : addrs) {
+        LOG(INFO) << "adbd listening on " << addr;
+        local_init(addr);
+    }
 }
 
 int adbd_main(int server_port) {
@@ -205,7 +222,11 @@
     // descriptor will always be open.
     adbd_cloexec_auth_socket();
 
-#if defined(ALLOW_ADBD_NO_AUTH)
+#if defined(__ANDROID_RECOVERY__)
+    if (is_device_unlocked() || __android_log_is_debuggable()) {
+        auth_required = false;
+    }
+#elif defined(ALLOW_ADBD_NO_AUTH)
     // If ro.adb.secure is unset, default to no authentication required.
     auth_required = android::base::GetBoolProperty("ro.adb.secure", false);
 #elif defined(__ANDROID__)
@@ -214,8 +235,6 @@
     }
 #endif
 
-    adbd_auth_init();
-
     // Our external storage path may be different than apps, since
     // we aren't able to bind mount after dropping root.
     const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
@@ -230,6 +249,9 @@
     drop_privileges(server_port);
 #endif
 
+    // adbd_auth_init will spawn a thread, so we need to defer it until after selinux transitions.
+    adbd_auth_init();
+
     bool is_usb = false;
 
 #if defined(__ANDROID__)
@@ -243,19 +265,38 @@
     // If one of these properties is set, also listen on that port.
     // If one of the properties isn't set and we couldn't listen on usb, listen
     // on the default port.
-    std::string prop_port = android::base::GetProperty("service.adb.tcp.port", "");
-    if (prop_port.empty()) {
-        prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
-    }
+    std::vector<std::string> addrs;
+    std::string prop_addr = android::base::GetProperty("service.adb.listen_addrs", "");
+    if (prop_addr.empty()) {
+        std::string prop_port = android::base::GetProperty("service.adb.tcp.port", "");
+        if (prop_port.empty()) {
+            prop_port = android::base::GetProperty("persist.adb.tcp.port", "");
+        }
 
-    int port;
-    if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
-        D("using port=%d", port);
-        // Listen on TCP port specified by service.adb.tcp.port property.
-        setup_port(port);
-    } else if (!is_usb) {
-        // Listen on default port.
-        setup_port(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
+#if !defined(__ANDROID__)
+        if (prop_port.empty() && getenv("ADBD_PORT")) {
+            prop_port = getenv("ADBD_PORT");
+        }
+#endif
+
+        int port;
+        if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {
+            D("using tcp port=%d", port);
+            // Listen on TCP and VSOCK port specified by service.adb.tcp.port property.
+            addrs.push_back(android::base::StringPrintf("tcp:%d", port));
+            addrs.push_back(android::base::StringPrintf("vsock:%d", port));
+            setup_adb(addrs);
+        } else if (!is_usb) {
+            // Listen on default port.
+            addrs.push_back(
+                    android::base::StringPrintf("tcp:%d", DEFAULT_ADB_LOCAL_TRANSPORT_PORT));
+            addrs.push_back(
+                    android::base::StringPrintf("vsock:%d", DEFAULT_ADB_LOCAL_TRANSPORT_PORT));
+            setup_adb(addrs);
+        }
+    } else {
+        addrs = android::base::Split(prop_addr, ",");
+        setup_adb(addrs);
     }
 
     D("adbd_main(): pre init_jdwp()");
diff --git a/adb/daemon/reboot_service.cpp b/adb/daemon/reboot_service.cpp
deleted file mode 100644
index a5a11b8..0000000
--- a/adb/daemon/reboot_service.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 TRACE_TAG SERVICES
-
-#include "sysdeps.h"
-
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <string>
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <bootloader_message/bootloader_message.h>
-#include <cutils/android_reboot.h>
-
-#include "adb_io.h"
-#include "adb_unique_fd.h"
-
-void reboot_service(unique_fd fd, const std::string& arg) {
-    std::string reboot_arg = arg;
-    sync();
-
-    if (reboot_arg.empty()) reboot_arg = "adb";
-    std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str());
-
-    if (reboot_arg == "fastboot" &&
-        android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) &&
-        access("/dev/socket/recovery", F_OK) == 0) {
-        LOG(INFO) << "Recovery specific reboot fastboot";
-        /*
-         * The socket is created to allow switching between recovery and
-         * fastboot.
-         */
-        android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
-        if (sock < 0) {
-            WriteFdFmt(fd, "reboot (%s) create\n", strerror(errno));
-            PLOG(ERROR) << "Creating recovery socket failed";
-            return;
-        }
-
-        sockaddr_un addr = {.sun_family = AF_UNIX};
-        strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
-        if (connect(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
-            WriteFdFmt(fd, "reboot (%s) connect\n", strerror(errno));
-            PLOG(ERROR) << "Couldn't connect to recovery socket";
-            return;
-        }
-        const char msg_switch_to_fastboot = 'f';
-        auto ret = adb_write(sock, &msg_switch_to_fastboot, sizeof(msg_switch_to_fastboot));
-        if (ret != sizeof(msg_switch_to_fastboot)) {
-            WriteFdFmt(fd, "reboot (%s) write\n", strerror(errno));
-            PLOG(ERROR) << "Couldn't write message to recovery socket to switch to fastboot";
-            return;
-        }
-    } else {
-        if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
-            WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str());
-            return;
-        }
-    }
-    // Don't return early. Give the reboot command time to take effect
-    // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
-    while (true) {
-        pause();
-    }
-}
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
deleted file mode 100644
index ce494ee..0000000
--- a/adb/daemon/remount_service.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2008 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 <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "adb.h"
-#include "adb_io.h"
-#include "adb_unique_fd.h"
-
-static constexpr char kRemountCmd[] = "/system/bin/remount";
-
-static bool do_remount(int fd, const std::string& cmd) {
-    if (getuid() != 0) {
-        WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
-        return false;
-    }
-
-    auto pid = fork();
-    if (pid < 0) {
-        WriteFdFmt(fd, "Failed to fork to %s: %s\n", kRemountCmd, strerror(errno));
-        return false;
-    }
-
-    if (pid == 0) {
-        // child side of the fork
-        dup2(fd, STDIN_FILENO);
-        dup2(fd, STDOUT_FILENO);
-        dup2(fd, STDERR_FILENO);
-
-        execl(kRemountCmd, kRemountCmd, cmd.empty() ? nullptr : cmd.c_str(), nullptr);
-        _exit(errno);
-    }
-
-    int wstatus = 0;
-    auto ret = waitpid(pid, &wstatus, 0);
-
-    if (ret == -1) {
-        WriteFdFmt(fd, "Failed to wait for %s: %s\n", kRemountCmd, strerror(errno));
-        return false;
-    } else if (ret != pid) {
-        WriteFdFmt(fd, "pid %d and waitpid return %d do not match for %s\n",
-                   static_cast<int>(pid), static_cast<int>(ret), kRemountCmd);
-        return false;
-    }
-
-    if (WIFSIGNALED(wstatus)) {
-        WriteFdFmt(fd, "%s terminated with signal %s\n", kRemountCmd,
-                   strsignal(WTERMSIG(wstatus)));
-        return false;
-    }
-
-    if (!WIFEXITED(wstatus)) {
-        WriteFdFmt(fd, "%s stopped with status 0x%x\n", kRemountCmd, wstatus);
-        return false;
-    }
-
-    if (WEXITSTATUS(wstatus)) {
-        WriteFdFmt(fd, "%s exited with status %d\n", kRemountCmd, WEXITSTATUS(wstatus));
-        return false;
-    }
-
-    return true;
-}
-
-void remount_service(unique_fd fd, const std::string& cmd) {
-    const char* success = do_remount(fd.get(), cmd) ? "succeeded" : "failed";
-    WriteFdFmt(fd.get(), "remount %s\n", success);
-}
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index b0cc450..4ec90d2 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -39,6 +39,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <cutils/android_reboot.h>
 #include <cutils/sockets.h>
 #include <log/log_properties.h>
 
@@ -53,10 +54,7 @@
 
 #include "daemon/file_sync_service.h"
 #include "daemon/framebuffer_service.h"
-#include "daemon/reboot_service.h"
-#include "daemon/remount_service.h"
 #include "daemon/restart_service.h"
-#include "daemon/set_verity_enable_state_service.h"
 #include "daemon/shell_service.h"
 
 
@@ -143,6 +141,26 @@
     WriteFdExactly(fd.get(), "spinning\n");
 }
 
+[[maybe_unused]] static unique_fd reboot_device(const std::string& name) {
+#if defined(__ANDROID_RECOVERY__)
+    if (!__android_log_is_debuggable()) {
+        auto reboot_service = [name](unique_fd fd) {
+            std::string reboot_string = android::base::StringPrintf("reboot,%s", name.c_str());
+            if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
+                WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str());
+                return;
+            }
+            while (true) pause();
+        };
+        return create_service_thread("reboot", reboot_service);
+    }
+#endif
+    // Fall through
+    std::string cmd = "/system/bin/reboot ";
+    cmd += name;
+    return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
+}
+
 struct ServiceSocket : public asocket {
     ServiceSocket() {
         install_local_socket(this);
@@ -223,13 +241,13 @@
         return create_jdwp_service_socket();
     } else if (name == "track-jdwp") {
         return create_jdwp_tracker_service_socket();
-    } else if (ConsumePrefix(&name, "sink:")) {
+    } else if (android::base::ConsumePrefix(&name, "sink:")) {
         uint64_t byte_count = 0;
         if (!ParseUint(&byte_count, name)) {
             return nullptr;
         }
         return new SinkSocket(byte_count);
-    } else if (ConsumePrefix(&name, "source:")) {
+    } else if (android::base::ConsumePrefix(&name, "source:")) {
         uint64_t byte_count = 0;
         if (!ParseUint(&byte_count, name)) {
             return nullptr;
@@ -250,19 +268,17 @@
 #if defined(__ANDROID__)
     if (name.starts_with("framebuffer:")) {
         return create_service_thread("fb", framebuffer_service);
-    } else if (ConsumePrefix(&name, "remount:")) {
-        std::string arg(name);
-        return create_service_thread("remount",
-                                     std::bind(remount_service, std::placeholders::_1, arg));
-    } else if (ConsumePrefix(&name, "reboot:")) {
-        std::string arg(name);
-        return create_service_thread("reboot",
-                                     std::bind(reboot_service, std::placeholders::_1, arg));
+    } else if (android::base::ConsumePrefix(&name, "remount:")) {
+        std::string cmd = "/system/bin/remount ";
+        cmd += name;
+        return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
+    } else if (android::base::ConsumePrefix(&name, "reboot:")) {
+        return reboot_device(std::string(name));
     } else if (name.starts_with("root:")) {
         return create_service_thread("root", restart_root_service);
     } else if (name.starts_with("unroot:")) {
         return create_service_thread("unroot", restart_unroot_service);
-    } else if (ConsumePrefix(&name, "backup:")) {
+    } else if (android::base::ConsumePrefix(&name, "backup:")) {
         std::string cmd = "/system/bin/bu backup ";
         cmd += name;
         return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
@@ -270,12 +286,12 @@
         return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
                                SubprocessProtocol::kNone);
     } else if (name.starts_with("disable-verity:")) {
-        return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
-                                                            std::placeholders::_1, false));
+        return StartSubprocess("/system/bin/disable-verity", nullptr, SubprocessType::kRaw,
+                               SubprocessProtocol::kNone);
     } else if (name.starts_with("enable-verity:")) {
-        return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service,
-                                                             std::placeholders::_1, true));
-    } else if (ConsumePrefix(&name, "tcpip:")) {
+        return StartSubprocess("/system/bin/enable-verity", nullptr, SubprocessType::kRaw,
+                               SubprocessProtocol::kNone);
+    } else if (android::base::ConsumePrefix(&name, "tcpip:")) {
         std::string str(name);
 
         int port;
@@ -289,22 +305,22 @@
     }
 #endif
 
-    if (ConsumePrefix(&name, "dev:")) {
+    if (android::base::ConsumePrefix(&name, "dev:")) {
         return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
-    } else if (ConsumePrefix(&name, "jdwp:")) {
+    } else if (android::base::ConsumePrefix(&name, "jdwp:")) {
         pid_t pid;
         if (!ParseUint(&pid, name)) {
             return unique_fd{};
         }
         return create_jdwp_connection_fd(pid);
-    } else if (ConsumePrefix(&name, "shell")) {
+    } else if (android::base::ConsumePrefix(&name, "shell")) {
         return ShellService(name, transport);
-    } else if (ConsumePrefix(&name, "exec:")) {
+    } else if (android::base::ConsumePrefix(&name, "exec:")) {
         return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
                                SubprocessProtocol::kNone);
     } else if (name.starts_with("sync:")) {
         return create_service_thread("sync", file_sync_service);
-    } else if (ConsumePrefix(&name, "reverse:")) {
+    } else if (android::base::ConsumePrefix(&name, "reverse:")) {
         return reverse_service(name, transport);
     } else if (name == "reconnect") {
         return create_service_thread(
diff --git a/adb/daemon/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp
deleted file mode 100644
index 889229f..0000000
--- a/adb/daemon/set_verity_enable_state_service.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2014 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 TRACE_TAG ADB
-
-#include "set_verity_enable_state_service.h"
-#include "sysdeps.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <libavb_user/libavb_user.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <fs_mgr.h>
-#include <fs_mgr_overlayfs.h>
-#include <fstab/fstab.h>
-#include <log/log_properties.h>
-
-#include "adb.h"
-#include "adb_io.h"
-#include "adb_unique_fd.h"
-
-#include "fec/io.h"
-
-#ifdef ALLOW_ADBD_DISABLE_VERITY
-static const bool kAllowDisableVerity = true;
-#else
-static const bool kAllowDisableVerity = false;
-#endif
-
-void suggest_run_adb_root(int fd) {
-    if (getuid() != 0) WriteFdExactly(fd, "Maybe run adb root?\n");
-}
-
-static bool make_block_device_writable(const std::string& dev) {
-    unique_fd fd(unix_open(dev, O_RDONLY | O_CLOEXEC));
-    if (fd == -1) {
-        return false;
-    }
-
-    int OFF = 0;
-    bool result = (ioctl(fd, BLKROSET, &OFF) != -1);
-    return result;
-}
-
-/* Turn verity on/off */
-static bool set_verity_enabled_state(int fd, const char* block_device, const char* mount_point,
-                                     bool enable) {
-    if (!make_block_device_writable(block_device)) {
-        WriteFdFmt(fd, "Could not make block device %s writable (%s).\n",
-                   block_device, strerror(errno));
-        return false;
-    }
-
-    fec::io fh(block_device, O_RDWR);
-
-    if (!fh) {
-        WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno));
-        suggest_run_adb_root(fd);
-        return false;
-    }
-
-    fec_verity_metadata metadata;
-
-    if (!fh.get_verity_metadata(metadata)) {
-        WriteFdExactly(fd, "Couldn't find verity metadata!\n");
-        return false;
-    }
-
-    if (!enable && metadata.disabled) {
-        WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point);
-        return false;
-    }
-
-    if (enable && !metadata.disabled) {
-        WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point);
-        return false;
-    }
-
-    if (!fh.set_verity_status(enable)) {
-        WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n",
-                   enable ? "enabled" : "disabled",
-                   block_device, strerror(errno));
-        return false;
-    }
-
-    auto change = false;
-    errno = 0;
-    if (enable ? fs_mgr_overlayfs_teardown(mount_point, &change)
-               : fs_mgr_overlayfs_setup(nullptr, mount_point, &change)) {
-        if (change) {
-            WriteFdFmt(fd, "%s overlayfs for %s\n", enable ? "disabling" : "using", mount_point);
-        }
-    } else if (errno) {
-        WriteFdFmt(fd, "Overlayfs %s for %s failed with error %s\n", enable ? "teardown" : "setup",
-                   mount_point, strerror(errno));
-    }
-    WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
-    return true;
-}
-
-/* Helper function to get A/B suffix, if any. If the device isn't
- * using A/B the empty string is returned. Otherwise either "_a",
- * "_b", ... is returned.
- */
-static std::string get_ab_suffix() {
-    return android::base::GetProperty("ro.boot.slot_suffix", "");
-}
-
-static bool is_avb_device_locked() {
-    return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
-}
-
-static bool overlayfs_setup(int fd, bool enable) {
-    auto change = false;
-    errno = 0;
-    if (enable ? fs_mgr_overlayfs_teardown(nullptr, &change)
-               : fs_mgr_overlayfs_setup(nullptr, nullptr, &change)) {
-        if (change) {
-            WriteFdFmt(fd, "%s overlayfs\n", enable ? "disabling" : "using");
-        }
-    } else if (errno) {
-        WriteFdFmt(fd, "Overlayfs %s failed with error %s\n", enable ? "teardown" : "setup",
-                   strerror(errno));
-        suggest_run_adb_root(fd);
-    }
-    return change;
-}
-
-/* Use AVB to turn verity on/off */
-static bool set_avb_verity_enabled_state(int fd, AvbOps* ops, bool enable_verity) {
-    std::string ab_suffix = get_ab_suffix();
-    bool verity_enabled;
-
-    if (is_avb_device_locked()) {
-        WriteFdExactly(fd, "Device is locked. Please unlock the device first\n");
-        return false;
-    }
-
-    if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) {
-        WriteFdExactly(fd, "Error getting verity state. Try adb root first?\n");
-        return false;
-    }
-
-    if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
-        WriteFdFmt(fd, "verity is already %s\n", verity_enabled ? "enabled" : "disabled");
-        return false;
-    }
-
-    if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) {
-        WriteFdExactly(fd, "Error setting verity\n");
-        return false;
-    }
-
-    overlayfs_setup(fd, enable_verity);
-    WriteFdFmt(fd, "Successfully %s verity\n", enable_verity ? "enabled" : "disabled");
-    return true;
-}
-
-void set_verity_enabled_state_service(unique_fd fd, bool enable) {
-    bool any_changed = false;
-
-    // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
-    // contract, androidboot.vbmeta.digest is set by the bootloader
-    // when using AVB).
-    bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
-
-    // If using AVB, dm-verity is used on any build so we want it to
-    // be possible to disable/enable on any build (except USER). For
-    // VB1.0 dm-verity is only enabled on certain builds.
-    if (!using_avb) {
-        if (!kAllowDisableVerity) {
-            WriteFdFmt(fd.get(), "%s-verity only works for userdebug builds\n",
-                       enable ? "enable" : "disable");
-        }
-
-        if (!android::base::GetBoolProperty("ro.secure", false)) {
-            overlayfs_setup(fd, enable);
-            WriteFdExactly(fd.get(), "verity not enabled - ENG build\n");
-            return;
-        }
-    }
-
-    // Should never be possible to disable dm-verity on a USER build
-    // regardless of using AVB or VB1.0.
-    if (!__android_log_is_debuggable()) {
-        WriteFdExactly(fd.get(), "verity cannot be disabled/enabled - USER build\n");
-        return;
-    }
-
-    if (using_avb) {
-        // Yep, the system is using AVB.
-        AvbOps* ops = avb_ops_user_new();
-        if (ops == nullptr) {
-            WriteFdExactly(fd.get(), "Error getting AVB ops\n");
-            return;
-        }
-        if (set_avb_verity_enabled_state(fd.get(), ops, enable)) {
-            any_changed = true;
-        }
-        avb_ops_user_free(ops);
-    } else {
-        // Not using AVB - assume VB1.0.
-
-        // read all fstab entries at once from all sources
-        android::fs_mgr::Fstab fstab;
-        if (!android::fs_mgr::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 (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;
-                }
-            }
-        }
-    }
-    if (!any_changed) any_changed = overlayfs_setup(fd, enable);
-
-    if (any_changed) {
-        WriteFdExactly(fd.get(), "Now reboot your device for settings to take effect\n");
-    }
-}
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 3c8f393..f62032d 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -85,7 +85,6 @@
 #include <paths.h>
 #include <pty.h>
 #include <pwd.h>
-#include <sys/select.h>
 #include <termios.h>
 
 #include <memory>
@@ -114,7 +113,7 @@
 namespace {
 
 // Reads from |fd| until close or failure.
-std::string ReadAll(int fd) {
+std::string ReadAll(borrowed_fd fd) {
     char buffer[512];
     std::string received;
 
@@ -141,6 +140,20 @@
     return true;
 }
 
+struct SubprocessPollfds {
+    adb_pollfd pfds[3];
+
+    adb_pollfd* data() { return pfds; }
+    size_t size() { return 3; }
+
+    adb_pollfd* begin() { return pfds; }
+    adb_pollfd* end() { return pfds + size(); }
+
+    adb_pollfd& stdinout_pfd() { return pfds[0]; }
+    adb_pollfd& stderr_pfd() { return pfds[1]; }
+    adb_pollfd& protocol_pfd() { return pfds[2]; }
+};
+
 class Subprocess {
   public:
     Subprocess(std::string command, const char* terminal_type, SubprocessType type,
@@ -176,8 +189,7 @@
     void PassDataStreams();
     void WaitForExit();
 
-    unique_fd* SelectLoop(fd_set* master_read_set_ptr,
-                          fd_set* master_write_set_ptr);
+    unique_fd* PollLoop(SubprocessPollfds* pfds);
 
     // Input/output stream handlers. Success returns nullptr, failure returns
     // a pointer to the failed FD.
@@ -222,7 +234,7 @@
 bool Subprocess::ForkAndExec(std::string* error) {
     unique_fd child_stdinout_sfd, child_stderr_sfd;
     unique_fd parent_error_sfd, child_error_sfd;
-    char pts_name[PATH_MAX];
+    const char* pts_name = nullptr;
 
     if (command_.empty()) {
         __android_log_security_bswrite(SEC_TAG_ADB_SHELL_INTERACTIVE, "");
@@ -283,10 +295,22 @@
     cenv.push_back(nullptr);
 
     if (type_ == SubprocessType::kPty) {
-        int fd;
-        pid_ = forkpty(&fd, pts_name, nullptr, nullptr);
+        unique_fd pty_master(posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC));
+        if (pty_master == -1) {
+            *error =
+                    android::base::StringPrintf("failed to create pty master: %s", strerror(errno));
+            return false;
+        }
+        if (unlockpt(pty_master.get()) != 0) {
+            *error = android::base::StringPrintf("failed to unlockpt pty master: %s",
+                                                 strerror(errno));
+            return false;
+        }
+
+        pid_ = fork();
+        pts_name = ptsname(pty_master.get());
         if (pid_ > 0) {
-          stdinout_sfd_.reset(fd);
+            stdinout_sfd_ = std::move(pty_master);
         }
     } else {
         if (!CreateSocketpair(&stdinout_sfd_, &child_stdinout_sfd)) {
@@ -317,9 +341,10 @@
             child_stdinout_sfd.reset(OpenPtyChildFd(pts_name, &child_error_sfd));
         }
 
-        dup2(child_stdinout_sfd, STDIN_FILENO);
-        dup2(child_stdinout_sfd, STDOUT_FILENO);
-        dup2(child_stderr_sfd != -1 ? child_stderr_sfd : child_stdinout_sfd, STDERR_FILENO);
+        dup2(child_stdinout_sfd.get(), STDIN_FILENO);
+        dup2(child_stdinout_sfd.get(), STDOUT_FILENO);
+        dup2(child_stderr_sfd != -1 ? child_stderr_sfd.get() : child_stdinout_sfd.get(),
+             STDERR_FILENO);
 
         // exec doesn't trigger destructors, close the FDs manually.
         stdinout_sfd_.reset(-1);
@@ -415,7 +440,7 @@
         }
     } else {
         // Raw protocol doesn't support multiple output streams, so combine stdout and stderr.
-        child_stderr_sfd.reset(dup(child_stdinout_sfd));
+        child_stderr_sfd.reset(dup(child_stdinout_sfd.get()));
     }
 
     D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(),
@@ -532,23 +557,23 @@
     }
 
     // Start by trying to read from the protocol FD, stdout, and stderr.
-    fd_set master_read_set, master_write_set;
-    FD_ZERO(&master_read_set);
-    FD_ZERO(&master_write_set);
-    for (unique_fd* sfd : {&protocol_sfd_, &stdinout_sfd_, &stderr_sfd_}) {
-        if (*sfd != -1) {
-            FD_SET(*sfd, &master_read_set);
-        }
-    }
+    SubprocessPollfds pfds;
+    pfds.stdinout_pfd() = {.fd = stdinout_sfd_.get(), .events = POLLIN};
+    pfds.stderr_pfd() = {.fd = stderr_sfd_.get(), .events = POLLIN};
+    pfds.protocol_pfd() = {.fd = protocol_sfd_.get(), .events = POLLIN};
 
     // Pass data until the protocol FD or both the subprocess pipes die, at
     // which point we can't pass any more data.
     while (protocol_sfd_ != -1 && (stdinout_sfd_ != -1 || stderr_sfd_ != -1)) {
-        unique_fd* dead_sfd = SelectLoop(&master_read_set, &master_write_set);
+        unique_fd* dead_sfd = PollLoop(&pfds);
         if (dead_sfd) {
             D("closing FD %d", dead_sfd->get());
-            FD_CLR(*dead_sfd, &master_read_set);
-            FD_CLR(*dead_sfd, &master_write_set);
+            auto it = std::find_if(pfds.begin(), pfds.end(), [=](const adb_pollfd& pfd) {
+                return pfd.fd == dead_sfd->get();
+            });
+            CHECK(it != pfds.end());
+            it->fd = -1;
+            it->events = 0;
             if (dead_sfd == &protocol_sfd_) {
                 // Using SIGHUP is a decent general way to indicate that the
                 // controlling process is going away. If specific signals are
@@ -570,29 +595,19 @@
     }
 }
 
-namespace {
-
-inline bool ValidAndInSet(const unique_fd& sfd, fd_set* set) {
-    return sfd != -1 && FD_ISSET(sfd, set);
-}
-
-}   // namespace
-
-unique_fd* Subprocess::SelectLoop(fd_set* master_read_set_ptr,
-                                  fd_set* master_write_set_ptr) {
-    fd_set read_set, write_set;
-    int select_n = std::max(std::max(protocol_sfd_, stdinout_sfd_), stderr_sfd_) + 1;
+unique_fd* Subprocess::PollLoop(SubprocessPollfds* pfds) {
     unique_fd* dead_sfd = nullptr;
+    adb_pollfd& stdinout_pfd = pfds->stdinout_pfd();
+    adb_pollfd& stderr_pfd = pfds->stderr_pfd();
+    adb_pollfd& protocol_pfd = pfds->protocol_pfd();
 
-    // Keep calling select() and passing data until an FD closes/errors.
+    // Keep calling poll() and passing data until an FD closes/errors.
     while (!dead_sfd) {
-        memcpy(&read_set, master_read_set_ptr, sizeof(read_set));
-        memcpy(&write_set, master_write_set_ptr, sizeof(write_set));
-        if (select(select_n, &read_set, &write_set, nullptr, nullptr) < 0) {
+        if (adb_poll(pfds->data(), pfds->size(), -1) < 0) {
             if (errno == EINTR) {
                 continue;
             } else {
-                PLOG(ERROR) << "select failed, closing subprocess pipes";
+                PLOG(ERROR) << "poll failed, closing subprocess pipes";
                 stdinout_sfd_.reset(-1);
                 stderr_sfd_.reset(-1);
                 return nullptr;
@@ -600,34 +615,47 @@
         }
 
         // Read stdout, write to protocol FD.
-        if (ValidAndInSet(stdinout_sfd_, &read_set)) {
+        if (stdinout_pfd.fd != -1 && (stdinout_pfd.revents & POLLIN)) {
             dead_sfd = PassOutput(&stdinout_sfd_, ShellProtocol::kIdStdout);
         }
 
         // Read stderr, write to protocol FD.
-        if (!dead_sfd && ValidAndInSet(stderr_sfd_, &read_set)) {
+        if (!dead_sfd && stderr_pfd.fd != 1 && (stderr_pfd.revents & POLLIN)) {
             dead_sfd = PassOutput(&stderr_sfd_, ShellProtocol::kIdStderr);
         }
 
         // Read protocol FD, write to stdin.
-        if (!dead_sfd && ValidAndInSet(protocol_sfd_, &read_set)) {
+        if (!dead_sfd && protocol_pfd.fd != -1 && (protocol_pfd.revents & POLLIN)) {
             dead_sfd = PassInput();
             // If we didn't finish writing, block on stdin write.
             if (input_bytes_left_) {
-                FD_CLR(protocol_sfd_, master_read_set_ptr);
-                FD_SET(stdinout_sfd_, master_write_set_ptr);
+                protocol_pfd.events &= ~POLLIN;
+                stdinout_pfd.events |= POLLOUT;
             }
         }
 
         // Continue writing to stdin; only happens if a previous write blocked.
-        if (!dead_sfd && ValidAndInSet(stdinout_sfd_, &write_set)) {
+        if (!dead_sfd && stdinout_pfd.fd != -1 && (stdinout_pfd.revents & POLLOUT)) {
             dead_sfd = PassInput();
             // If we finished writing, go back to blocking on protocol read.
             if (!input_bytes_left_) {
-                FD_SET(protocol_sfd_, master_read_set_ptr);
-                FD_CLR(stdinout_sfd_, master_write_set_ptr);
+                protocol_pfd.events |= POLLIN;
+                stdinout_pfd.events &= ~POLLOUT;
             }
         }
+
+        // After handling all of the events we've received, check to see if any fds have died.
+        if (stdinout_pfd.revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) {
+            return &stdinout_sfd_;
+        }
+
+        if (stderr_pfd.revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) {
+            return &stderr_sfd_;
+        }
+
+        if (protocol_pfd.revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)) {
+            return &protocol_sfd_;
+        }
     }  // while (!dead_sfd)
 
     return dead_sfd;
@@ -639,7 +667,7 @@
         if (!input_->Read()) {
             // Read() uses ReadFdExactly() which sets errno to 0 on EOF.
             if (errno != 0) {
-                PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_;
+                PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_.get();
             }
             return &protocol_sfd_;
         }
@@ -655,7 +683,7 @@
                         ws.ws_col = cols;
                         ws.ws_xpixel = x_pixels;
                         ws.ws_ypixel = y_pixels;
-                        ioctl(stdinout_sfd_, TIOCSWINSZ, &ws);
+                        ioctl(stdinout_sfd_.get(), TIOCSWINSZ, &ws);
                     }
                     break;
                 case ShellProtocol::kIdStdin:
@@ -666,8 +694,7 @@
                         if (adb_shutdown(stdinout_sfd_, SHUT_WR) == 0) {
                             return nullptr;
                         }
-                        PLOG(ERROR) << "failed to shutdown writes to FD "
-                                    << stdinout_sfd_;
+                        PLOG(ERROR) << "failed to shutdown writes to FD " << stdinout_sfd_.get();
                         return &stdinout_sfd_;
                     } else {
                         // PTYs can't close just input, so rather than close the
@@ -688,7 +715,7 @@
         int bytes = adb_write(stdinout_sfd_, input_->data() + index, input_bytes_left_);
         if (bytes == 0 || (bytes < 0 && errno != EAGAIN)) {
             if (bytes < 0) {
-                PLOG(ERROR) << "error reading stdin FD " << stdinout_sfd_;
+                PLOG(ERROR) << "error reading stdin FD " << stdinout_sfd_.get();
             }
             // stdin is done, mark this packet as finished and we'll just start
             // dumping any further data received from the protocol FD.
@@ -708,14 +735,14 @@
         // read() returns EIO if a PTY closes; don't report this as an error,
         // it just means the subprocess completed.
         if (bytes < 0 && !(type_ == SubprocessType::kPty && errno == EIO)) {
-            PLOG(ERROR) << "error reading output FD " << *sfd;
+            PLOG(ERROR) << "error reading output FD " << sfd->get();
         }
         return sfd;
     }
 
     if (bytes > 0 && !output_->Write(id, bytes)) {
         if (errno != 0) {
-            PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_;
+            PLOG(ERROR) << "error reading protocol FD " << protocol_sfd_.get();
         }
         return &protocol_sfd_;
     }
diff --git a/adb/daemon/shell_service.h b/adb/daemon/shell_service.h
index 3abd958..030228c 100644
--- a/adb/daemon/shell_service.h
+++ b/adb/daemon/shell_service.h
@@ -48,7 +48,7 @@
 // Sets up in/out and error streams to emulate shell-like behavior.
 //
 // Returns an open FD connected to the thread or -1 on failure.
-using Command = int(std::string_view args, int in, int out, int err);
+using Command = int(std::string_view args, borrowed_fd in, borrowed_fd out, borrowed_fd err);
 unique_fd StartCommandInProcess(std::string name, Command command, SubprocessProtocol protocol);
 
 // Create a pipe containing the error.
diff --git a/adb/daemon/shell_service_test.cpp b/adb/daemon/shell_service_test.cpp
index dc79d12..cdd8dbe 100644
--- a/adb/daemon/shell_service_test.cpp
+++ b/adb/daemon/shell_service_test.cpp
@@ -77,7 +77,7 @@
 namespace {
 
 // Reads raw data from |fd| until it closes or errors.
-std::string ReadRaw(int fd) {
+std::string ReadRaw(borrowed_fd fd) {
     char buffer[1024];
     char *cur_ptr = buffer, *end_ptr = buffer + sizeof(buffer);
 
@@ -93,12 +93,12 @@
 // Reads shell protocol data from |fd| until it closes or errors. Fills
 // |stdout| and |stderr| with their respective data, and returns the exit code
 // read from the protocol or -1 if an exit code packet was not received.
-int ReadShellProtocol(int fd, std::string* stdout, std::string* stderr) {
+int ReadShellProtocol(borrowed_fd fd, std::string* stdout, std::string* stderr) {
     int exit_code = -1;
     stdout->clear();
     stderr->clear();
 
-    auto protocol = std::make_unique<ShellProtocol>(fd);
+    auto protocol = std::make_unique<ShellProtocol>(fd.get());
     while (protocol->Read()) {
         switch (protocol->id()) {
             case ShellProtocol::kIdStdout:
diff --git a/adb/daemon/transport_qemu.cpp b/adb/daemon/transport_qemu.cpp
index aa760bc..901efee 100644
--- a/adb/daemon/transport_qemu.cpp
+++ b/adb/daemon/transport_qemu.cpp
@@ -18,6 +18,7 @@
 #include <qemu_pipe.h>
 
 #define TRACE_TAG TRANSPORT
+#include "socket_spec.h"
 #include "sysdeps.h"
 #include "transport.h"
 
@@ -55,7 +56,7 @@
  *   the transport registration is completed. That's why we need to send the
  *   'start' request after the transport is registered.
  */
-void qemu_socket_thread(int port) {
+void qemu_socket_thread(std::string_view addr) {
     /* 'accept' request to the adb QEMUD service. */
     static const char _accept_req[] = "accept";
     /* 'start' request to the adb QEMUD service. */
@@ -69,6 +70,12 @@
     adb_thread_setname("qemu socket");
     D("transport: qemu_socket_thread() starting");
 
+    std::string error;
+    int port = get_host_socket_spec_port(addr, &error);
+    if (port == -1) {
+        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+    }
+
     /* adb QEMUD service connection request. */
     snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
 
@@ -78,7 +85,7 @@
         /* This could be an older version of the emulator, that doesn't
          * implement adb QEMUD service. Fall back to the old TCP way. */
         D("adb service is not available. Falling back to TCP socket.");
-        std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
+        std::thread(server_socket_thread, adb_listen, addr).detach();
         return;
     }
 
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 1abae87..a9ad805 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -117,14 +117,18 @@
     }
 };
 
+template <class Payload>
 struct IoBlock {
     bool pending = false;
     struct iocb control = {};
-    std::shared_ptr<Block> payload;
+    Payload payload;
 
     TransferId id() const { return TransferId::from_value(control.aio_data); }
 };
 
+using IoReadBlock = IoBlock<Block>;
+using IoWriteBlock = IoBlock<std::shared_ptr<Block>>;
+
 struct ScopedAioContext {
     ScopedAioContext() = default;
     ~ScopedAioContext() { reset(); }
@@ -208,16 +212,17 @@
 
     virtual bool Write(std::unique_ptr<apacket> packet) override final {
         LOG(DEBUG) << "USB write: " << dump_header(&packet->msg);
-        Block header(sizeof(packet->msg));
-        memcpy(header.data(), &packet->msg, sizeof(packet->msg));
+        auto header = std::make_shared<Block>(sizeof(packet->msg));
+        memcpy(header->data(), &packet->msg, sizeof(packet->msg));
 
         std::lock_guard<std::mutex> lock(write_mutex_);
-        write_requests_.push_back(CreateWriteBlock(std::move(header), next_write_id_++));
+        write_requests_.push_back(
+                CreateWriteBlock(std::move(header), 0, sizeof(packet->msg), next_write_id_++));
         if (!packet->payload.empty()) {
             // The kernel attempts to allocate a contiguous block of memory for each write,
             // which can fail if the write is large and the kernel heap is fragmented.
             // Split large writes into smaller chunks to avoid this.
-            std::shared_ptr<Block> payload = std::make_shared<Block>(std::move(packet->payload));
+            auto payload = std::make_shared<Block>(std::move(packet->payload));
             size_t offset = 0;
             size_t len = payload->size();
 
@@ -464,16 +469,20 @@
         worker_thread_.join();
     }
 
-    void PrepareReadBlock(IoBlock* block, uint64_t id) {
+    void PrepareReadBlock(IoReadBlock* block, uint64_t id) {
         block->pending = false;
-        block->payload = std::make_shared<Block>(kUsbReadSize);
+        if (block->payload.capacity() >= kUsbReadSize) {
+            block->payload.resize(kUsbReadSize);
+        } else {
+            block->payload = Block(kUsbReadSize);
+        }
         block->control.aio_data = static_cast<uint64_t>(TransferId::read(id));
-        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload->data());
-        block->control.aio_nbytes = block->payload->size();
+        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload.data());
+        block->control.aio_nbytes = block->payload.size();
     }
 
-    IoBlock CreateReadBlock(uint64_t id) {
-        IoBlock block;
+    IoReadBlock CreateReadBlock(uint64_t id) {
+        IoReadBlock block;
         PrepareReadBlock(&block, id);
         block.control.aio_rw_flags = 0;
         block.control.aio_lio_opcode = IOCB_CMD_PREAD;
@@ -518,9 +527,9 @@
 
     void HandleRead(TransferId id, int64_t size) {
         uint64_t read_idx = id.id % kUsbReadQueueDepth;
-        IoBlock* block = &read_requests_[read_idx];
+        IoReadBlock* block = &read_requests_[read_idx];
         block->pending = false;
-        block->payload->resize(size);
+        block->payload.resize(size);
 
         // Notification for completed reads can be received out of order.
         if (block->id().id != needed_read_id_) {
@@ -531,7 +540,7 @@
 
         for (uint64_t id = needed_read_id_;; ++id) {
             size_t read_idx = id % kUsbReadQueueDepth;
-            IoBlock* current_block = &read_requests_[read_idx];
+            IoReadBlock* current_block = &read_requests_[read_idx];
             if (current_block->pending) {
                 break;
             }
@@ -540,19 +549,19 @@
         }
     }
 
-    void ProcessRead(IoBlock* block) {
-        if (!block->payload->empty()) {
+    void ProcessRead(IoReadBlock* block) {
+        if (!block->payload.empty()) {
             if (!incoming_header_.has_value()) {
-                CHECK_EQ(sizeof(amessage), block->payload->size());
-                amessage msg;
-                memcpy(&msg, block->payload->data(), sizeof(amessage));
+                CHECK_EQ(sizeof(amessage), block->payload.size());
+                amessage& msg = incoming_header_.emplace();
+                memcpy(&msg, block->payload.data(), sizeof(msg));
                 LOG(DEBUG) << "USB read:" << dump_header(&msg);
                 incoming_header_ = msg;
             } else {
                 size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
-                Block payload = std::move(*block->payload);
+                Block payload = std::move(block->payload);
                 CHECK_LE(payload.size(), bytes_left);
-                incoming_payload_.append(std::make_unique<Block>(std::move(payload)));
+                incoming_payload_.append(std::move(payload));
             }
 
             if (incoming_header_->data_length == incoming_payload_.size()) {
@@ -560,11 +569,15 @@
                 packet->msg = *incoming_header_;
 
                 // TODO: Make apacket contain an IOVector so we don't have to coalesce.
-                packet->payload = incoming_payload_.coalesce();
+                packet->payload = std::move(incoming_payload_).coalesce();
                 read_callback_(this, std::move(packet));
 
                 incoming_header_.reset();
-                incoming_payload_.clear();
+                // reuse the capacity of the incoming payload while we can.
+                auto free_block = incoming_payload_.clear();
+                if (block->payload.capacity() == 0) {
+                    block->payload = std::move(free_block);
+                }
             }
         }
 
@@ -572,7 +585,7 @@
         SubmitRead(block);
     }
 
-    bool SubmitRead(IoBlock* block) {
+    bool SubmitRead(IoReadBlock* block) {
         block->pending = true;
         struct iocb* iocb = &block->control;
         if (io_submit(aio_context_.get(), 1, &iocb) != 1) {
@@ -594,7 +607,7 @@
         std::lock_guard<std::mutex> lock(write_mutex_);
         auto it =
                 std::find_if(write_requests_.begin(), write_requests_.end(), [id](const auto& req) {
-                    return static_cast<uint64_t>(req->id()) == static_cast<uint64_t>(id);
+                    return static_cast<uint64_t>(req.id()) == static_cast<uint64_t>(id);
                 });
         CHECK(it != write_requests_.end());
 
@@ -605,27 +618,26 @@
         SubmitWrites();
     }
 
-    std::unique_ptr<IoBlock> CreateWriteBlock(std::shared_ptr<Block> payload, size_t offset,
-                                              size_t len, uint64_t id) {
-        auto block = std::make_unique<IoBlock>();
-        block->payload = std::move(payload);
-        block->control.aio_data = static_cast<uint64_t>(TransferId::write(id));
-        block->control.aio_rw_flags = 0;
-        block->control.aio_lio_opcode = IOCB_CMD_PWRITE;
-        block->control.aio_reqprio = 0;
-        block->control.aio_fildes = write_fd_.get();
-        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload->data() + offset);
-        block->control.aio_nbytes = len;
-        block->control.aio_offset = 0;
-        block->control.aio_flags = IOCB_FLAG_RESFD;
-        block->control.aio_resfd = worker_event_fd_.get();
+    IoWriteBlock CreateWriteBlock(std::shared_ptr<Block> payload, size_t offset, size_t len,
+                                  uint64_t id) {
+        auto block = IoWriteBlock();
+        block.payload = std::move(payload);
+        block.control.aio_data = static_cast<uint64_t>(TransferId::write(id));
+        block.control.aio_rw_flags = 0;
+        block.control.aio_lio_opcode = IOCB_CMD_PWRITE;
+        block.control.aio_reqprio = 0;
+        block.control.aio_fildes = write_fd_.get();
+        block.control.aio_buf = reinterpret_cast<uintptr_t>(block.payload->data() + offset);
+        block.control.aio_nbytes = len;
+        block.control.aio_offset = 0;
+        block.control.aio_flags = IOCB_FLAG_RESFD;
+        block.control.aio_resfd = worker_event_fd_.get();
         return block;
     }
 
-    std::unique_ptr<IoBlock> CreateWriteBlock(Block payload, uint64_t id) {
-        std::shared_ptr<Block> block = std::make_shared<Block>(std::move(payload));
-        size_t len = block->size();
-        return CreateWriteBlock(std::move(block), 0, len, id);
+    IoWriteBlock CreateWriteBlock(Block&& payload, uint64_t id) {
+        size_t len = payload.size();
+        return CreateWriteBlock(std::make_shared<Block>(std::move(payload)), 0, len, id);
     }
 
     void SubmitWrites() REQUIRES(write_mutex_) {
@@ -642,9 +654,9 @@
 
         struct iocb* iocbs[kUsbWriteQueueDepth];
         for (int i = 0; i < writes_to_submit; ++i) {
-            CHECK(!write_requests_[writes_submitted_ + i]->pending);
-            write_requests_[writes_submitted_ + i]->pending = true;
-            iocbs[i] = &write_requests_[writes_submitted_ + i]->control;
+            CHECK(!write_requests_[writes_submitted_ + i].pending);
+            write_requests_[writes_submitted_ + i].pending = true;
+            iocbs[i] = &write_requests_[writes_submitted_ + i].control;
             LOG(VERBOSE) << "submitting write_request " << static_cast<void*>(iocbs[i]);
         }
 
@@ -689,7 +701,7 @@
     std::optional<amessage> incoming_header_;
     IOVector incoming_payload_;
 
-    std::array<IoBlock, kUsbReadQueueDepth> read_requests_;
+    std::array<IoReadBlock, kUsbReadQueueDepth> read_requests_;
     IOVector read_data_;
 
     // ID of the next request that we're going to send out.
@@ -699,7 +711,7 @@
     size_t needed_read_id_ = 0;
 
     std::mutex write_mutex_;
-    std::deque<std::unique_ptr<IoBlock>> write_requests_ GUARDED_BY(write_mutex_);
+    std::deque<IoWriteBlock> write_requests_ GUARDED_BY(write_mutex_);
     size_t next_write_id_ GUARDED_BY(write_mutex_) = 0;
     size_t writes_submitted_ GUARDED_BY(write_mutex_) = 0;
 
diff --git a/adb/daemon/usb_ffs.cpp b/adb/daemon/usb_ffs.cpp
index 07b4ba8..b19fa5d 100644
--- a/adb/daemon/usb_ffs.cpp
+++ b/adb/daemon/usb_ffs.cpp
@@ -37,9 +37,12 @@
 // Number of buffers needed to fit MAX_PAYLOAD, with an extra for ZLPs.
 #define USB_FFS_NUM_BUFS ((4 * MAX_PAYLOAD / USB_FFS_BULK_SIZE) + 1)
 
+#define USB_EXT_PROP_UNICODE 1
+
 #define cpu_to_le16(x) htole16(x)
 #define cpu_to_le32(x) htole32(x)
 
+// clang-format off
 struct func_desc {
     struct usb_interface_descriptor intf;
     struct usb_endpoint_descriptor_no_audio source;
@@ -64,6 +67,34 @@
     struct func_desc fs_descs, hs_descs;
 } __attribute__((packed));
 
+template <size_t PropertyNameLength, size_t PropertyDataLength>
+struct usb_os_desc_ext_prop {
+    uint32_t dwSize = sizeof(*this);
+    uint32_t dwPropertyDataType = cpu_to_le32(USB_EXT_PROP_UNICODE);
+
+    // Property name and value are transmitted as UTF-16, but the kernel only
+    // accepts ASCII values and performs the conversion for us.
+    uint16_t wPropertyNameLength = cpu_to_le16(PropertyNameLength);
+    char bPropertyName[PropertyNameLength];
+
+    uint32_t dwPropertyDataLength = cpu_to_le32(PropertyDataLength);
+    char bProperty[PropertyDataLength];
+} __attribute__((packed));
+
+using usb_os_desc_guid_t = usb_os_desc_ext_prop<20, 39>;
+usb_os_desc_guid_t os_desc_guid = {
+    .bPropertyName = "DeviceInterfaceGUID",
+    .bProperty = "{F72FE0D4-CBCB-407D-8814-9ED673D0DD6B}",
+};
+
+struct usb_ext_prop_values {
+    usb_os_desc_guid_t guid;
+} __attribute__((packed));
+
+usb_ext_prop_values os_prop_values = {
+    .guid = os_desc_guid,
+};
+
 struct desc_v2 {
     struct usb_functionfs_descs_head_v2 header;
     // The rest of the structure depends on the flags in the header.
@@ -75,9 +106,10 @@
     struct ss_func_desc ss_descs;
     struct usb_os_desc_header os_header;
     struct usb_ext_compat_desc os_desc;
+    struct usb_os_desc_header os_prop_header;
+    struct usb_ext_prop_values os_prop_values;
 } __attribute__((packed));
 
-// clang-format off
 static struct func_desc fs_descriptors = {
     .intf = {
         .bLength = sizeof(fs_descriptors.intf),
@@ -172,13 +204,13 @@
 struct usb_ext_compat_desc os_desc_compat = {
     .bFirstInterfaceNumber = 0,
     .Reserved1 = cpu_to_le32(1),
-    .CompatibleID = {0},
+    .CompatibleID = { 'W', 'I', 'N', 'U', 'S', 'B', '\0', '\0'},
     .SubCompatibleID = {0},
     .Reserved2 = {0},
 };
 
 static struct usb_os_desc_header os_desc_header = {
-    .interface = cpu_to_le32(1),
+    .interface = cpu_to_le32(0),
     .dwLength = cpu_to_le32(sizeof(os_desc_header) + sizeof(os_desc_compat)),
     .bcdVersion = cpu_to_le32(1),
     .wIndex = cpu_to_le32(4),
@@ -186,6 +218,14 @@
     .Reserved = cpu_to_le32(0),
 };
 
+static struct usb_os_desc_header os_prop_header = {
+    .interface = cpu_to_le32(0),
+    .dwLength = cpu_to_le32(sizeof(os_desc_header) + sizeof(os_prop_values)),
+    .bcdVersion = cpu_to_le32(1),
+    .wIndex = cpu_to_le32(5),
+    .wCount = cpu_to_le16(1),
+};
+
 #define STR_INTERFACE_ "ADB Interface"
 
 static const struct {
@@ -221,12 +261,14 @@
     v2_descriptor.fs_count = 3;
     v2_descriptor.hs_count = 3;
     v2_descriptor.ss_count = 5;
-    v2_descriptor.os_count = 1;
+    v2_descriptor.os_count = 2;
     v2_descriptor.fs_descs = fs_descriptors;
     v2_descriptor.hs_descs = hs_descriptors;
     v2_descriptor.ss_descs = ss_descriptors;
     v2_descriptor.os_header = os_desc_header;
     v2_descriptor.os_desc = os_desc_compat;
+    v2_descriptor.os_prop_header = os_prop_header;
+    v2_descriptor.os_prop_values = os_prop_values;
 
     if (out_control->get() < 0) {  // might have already done this before
         LOG(INFO) << "opening control endpoint " << USB_FFS_ADB_EP0;
diff --git a/adb/fastdeploy/Android.bp b/adb/fastdeploy/Android.bp
index 1ba0de0..f5893aa 100644
--- a/adb/fastdeploy/Android.bp
+++ b/adb/fastdeploy/Android.bp
@@ -13,27 +13,77 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
+java_library {
+    name: "deployagent_lib",
+    sdk_version: "24",
+    srcs: [
+        "deployagent/src/**/*.java",
+        "proto/**/*.proto",
+    ],
+    proto: {
+        type: "lite",
+    },
+}
 
 java_binary {
     name: "deployagent",
     sdk_version: "24",
-    srcs: ["deployagent/src/**/*.java", "deploylib/src/**/*.java", "proto/**/*.proto"],
-    static_libs: ["apkzlib_zip"],
-    wrapper: "deployagent/deployagent.sh",
-    proto: {
-        type: "lite",
-    },
+    static_libs: [
+        "deployagent_lib",
+    ],
     dex_preopt: {
         enabled: false,
     }
 }
 
-java_binary_host {
-    name: "deploypatchgenerator",
-    srcs: ["deploypatchgenerator/src/**/*.java", "deploylib/src/**/*.java", "proto/**/*.proto"],
-    static_libs: ["apkzlib"],
-    manifest: "deploypatchgenerator/manifest.txt",
-    proto: {
-        type: "full",
-    }
+android_test {
+    name: "FastDeployTests",
+
+    manifest: "AndroidManifest.xml",
+
+    srcs: [
+        "deployagent/test/com/android/fastdeploy/ApkArchiveTest.java",
+    ],
+
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.runner",
+        "androidx.test.rules",
+        "deployagent_lib",
+        "mockito-target-inline-minus-junit4",
+    ],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+
+    data: [
+        "testdata/sample.apk",
+        "testdata/sample.cd",
+    ],
+
+    optimize: {
+        enabled: false,
+    },
+}
+
+java_test_host {
+    name: "FastDeployHostTests",
+    srcs: [
+        "deployagent/test/com/android/fastdeploy/FastDeployTest.java",
+    ],
+    data: [
+        "testdata/helloworld5.apk",
+        "testdata/helloworld7.apk",
+    ],
+    libs: [
+        "compatibility-host-util",
+        "cts-tradefed",
+        "tradefed",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
 }
diff --git a/adb/fastdeploy/AndroidManifest.xml b/adb/fastdeploy/AndroidManifest.xml
new file mode 100644
index 0000000..89dc745
--- /dev/null
+++ b/adb/fastdeploy/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.fastdeploytests">
+
+    <application android:testOnly="true"
+                 android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.fastdeploytests"
+        android:label="FastDeploy Tests" />
+</manifest>
\ No newline at end of file
diff --git a/adb/fastdeploy/AndroidTest.xml b/adb/fastdeploy/AndroidTest.xml
new file mode 100644
index 0000000..24a72bc
--- /dev/null
+++ b/adb/fastdeploy/AndroidTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+<configuration description="Runs Device Tests for FastDeploy.">
+    <option name="test-suite-tag" value="FastDeployTests"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true"/>
+        <option name="install-arg" value="-t"/>
+        <option name="test-file-name" value="FastDeployTests.apk"/>
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="false" />
+        <option name="push-file" key="sample.apk" value="/data/local/tmp/FastDeployTests/sample.apk" />
+        <option name="push-file" key="sample.cd" value="/data/local/tmp/FastDeployTests/sample.cd" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.fastdeploytests"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+    </test>
+
+    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+        <option name="jar" value="FastDeployHostTests.jar" />
+    </test>
+</configuration>
diff --git a/adb/fastdeploy/deployagent/deployagent.sh b/adb/fastdeploy/deployagent/deployagent.sh
index 4f17eb7..91576ca 100755
--- a/adb/fastdeploy/deployagent/deployagent.sh
+++ b/adb/fastdeploy/deployagent/deployagent.sh
@@ -1,7 +1,4 @@
-# Script to start "deployagent" on the device, which has a very rudimentary
-# shell.
-#
+#!/system/bin/sh
 base=/data/local/tmp
 export CLASSPATH=$base/deployagent.jar
 exec app_process $base com.android.fastdeploy.DeployAgent "$@"
-
diff --git a/adb/fastdeploy/deployagent/src/com/android/fastdeploy/ApkArchive.java b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/ApkArchive.java
new file mode 100644
index 0000000..31e0502
--- /dev/null
+++ b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/ApkArchive.java
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+package com.android.fastdeploy;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
+
+/**
+ * Extremely light-weight APK parser class.
+ * Aware of Central Directory, Local File Headers and Signature.
+ * No Zip64 support yet.
+ */
+public final class ApkArchive {
+    private static final String TAG = "ApkArchive";
+
+    // Central Directory constants.
+    private static final int EOCD_SIGNATURE = 0x06054b50;
+    private static final int EOCD_MIN_SIZE = 22;
+    private static final long EOCD_MAX_SIZE = 65_535L + EOCD_MIN_SIZE;
+
+    private static final int CD_ENTRY_HEADER_SIZE_BYTES = 22;
+    private static final int CD_LOCAL_FILE_HEADER_SIZE_OFFSET = 12;
+
+    // Signature constants.
+    private static final int EOSIGNATURE_SIZE = 24;
+
+    public final static class Dump {
+        final byte[] cd;
+        final byte[] signature;
+
+        Dump(byte[] cd, byte[] signature) {
+            this.cd = cd;
+            this.signature = signature;
+        }
+    }
+
+    final static class Location {
+        final long offset;
+        final long size;
+
+        public Location(long offset, long size) {
+            this.offset = offset;
+            this.size = size;
+        }
+    }
+
+    private final RandomAccessFile mFile;
+    private final FileChannel mChannel;
+
+    public ApkArchive(File apk) throws IOException {
+        mFile = new RandomAccessFile(apk, "r");
+        mChannel = mFile.getChannel();
+    }
+
+    /**
+     * Extract the APK metadata: content of Central Directory and Signature.
+     *
+     * @return raw content from APK representing CD and Signature data.
+     */
+    public Dump extractMetadata() throws IOException {
+        Location cdLoc = getCDLocation();
+        byte[] cd = readMetadata(cdLoc);
+
+        byte[] signature = null;
+        Location sigLoc = getSignatureLocation(cdLoc.offset);
+        if (sigLoc != null) {
+            signature = readMetadata(sigLoc);
+            long size = ByteBuffer.wrap(signature).order(ByteOrder.LITTLE_ENDIAN).getLong();
+            if (sigLoc.size != size) {
+                Log.e(TAG, "Mismatching signature sizes: " + sigLoc.size + " != " + size);
+                signature = null;
+            }
+        }
+
+        return new Dump(cd, signature);
+    }
+
+    private long findEndOfCDRecord() throws IOException {
+        final long fileSize = mChannel.size();
+        int sizeToRead = Math.toIntExact(Math.min(fileSize, EOCD_MAX_SIZE));
+        final long readOffset = fileSize - sizeToRead;
+        ByteBuffer buffer = mChannel.map(FileChannel.MapMode.READ_ONLY, readOffset,
+                sizeToRead).order(ByteOrder.LITTLE_ENDIAN);
+
+        buffer.position(sizeToRead - EOCD_MIN_SIZE);
+        while (true) {
+            int signature = buffer.getInt(); // Read 4 bytes.
+            if (signature == EOCD_SIGNATURE) {
+                return readOffset + buffer.position() - 4;
+            }
+            if (buffer.position() == 4) {
+                break;
+            }
+            buffer.position(buffer.position() - Integer.BYTES - 1); // Backtrack 5 bytes.
+        }
+
+        return -1L;
+    }
+
+    private Location findCDRecord(ByteBuffer buf) {
+        if (buf.order() != ByteOrder.LITTLE_ENDIAN) {
+            throw new IllegalArgumentException("ByteBuffer byte order must be little endian");
+        }
+        if (buf.remaining() < CD_ENTRY_HEADER_SIZE_BYTES) {
+            throw new IllegalArgumentException(
+                    "Input too short. Need at least " + CD_ENTRY_HEADER_SIZE_BYTES
+                            + " bytes, available: " + buf.remaining() + "bytes.");
+        }
+
+        int originalPosition = buf.position();
+        int recordSignature = buf.getInt();
+        if (recordSignature != EOCD_SIGNATURE) {
+            throw new IllegalArgumentException(
+                    "Not a Central Directory record. Signature: 0x"
+                            + Long.toHexString(recordSignature & 0xffffffffL));
+        }
+
+        buf.position(originalPosition + CD_LOCAL_FILE_HEADER_SIZE_OFFSET);
+        long size = buf.getInt() & 0xffffffffL;
+        long offset = buf.getInt() & 0xffffffffL;
+        return new Location(offset, size);
+    }
+
+    // Retrieve the location of the Central Directory Record.
+    Location getCDLocation() throws IOException {
+        long eocdRecord = findEndOfCDRecord();
+        if (eocdRecord < 0) {
+            throw new IllegalArgumentException("Unable to find End of Central Directory record.");
+        }
+
+        Location location = findCDRecord(mChannel.map(FileChannel.MapMode.READ_ONLY, eocdRecord,
+                CD_ENTRY_HEADER_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN));
+        if (location == null) {
+            throw new IllegalArgumentException("Unable to find Central Directory File Header.");
+        }
+
+        return location;
+    }
+
+    // Retrieve the location of the signature block starting from Central
+    // Directory Record or null if signature is not found.
+    Location getSignatureLocation(long cdRecordOffset) throws IOException {
+        long signatureOffset = cdRecordOffset - EOSIGNATURE_SIZE;
+        if (signatureOffset < 0) {
+            Log.e(TAG, "Unable to find Signature.");
+            return null;
+        }
+
+        ByteBuffer signature = mChannel.map(FileChannel.MapMode.READ_ONLY, signatureOffset,
+                EOSIGNATURE_SIZE).order(ByteOrder.LITTLE_ENDIAN);
+
+        long size = signature.getLong();
+
+        byte[] sign = new byte[16];
+        signature.get(sign);
+        String signAsString = new String(sign);
+        if (!"APK Sig Block 42".equals(signAsString)) {
+            Log.e(TAG, "Signature magic does not match: " + signAsString);
+            return null;
+        }
+
+        long offset = cdRecordOffset - size - 8;
+
+        return new Location(offset, size);
+    }
+
+    private byte[] readMetadata(Location loc) throws IOException {
+        byte[] payload = new byte[(int) loc.size];
+        ByteBuffer buffer = mChannel.map(FileChannel.MapMode.READ_ONLY, loc.offset, loc.size);
+        buffer.get(payload);
+        return payload;
+    }
+}
diff --git a/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
index 2d3b135..3812307 100644
--- a/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
+++ b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/DeployAgent.java
@@ -24,18 +24,22 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.TimeUnit;
-import java.io.OutputStream;
 import java.io.RandomAccessFile;
-import java.util.Set;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.WritableByteChannel;
 
+import com.android.fastdeploy.PatchFormatException;
+import com.android.fastdeploy.ApkArchive;
+import com.android.fastdeploy.APKDump;
 import com.android.fastdeploy.APKMetaData;
 import com.android.fastdeploy.PatchUtils;
 
+import com.google.protobuf.ByteString;
+
 public final class DeployAgent {
     private static final int BUFFER_SIZE = 128 * 1024;
-    private static final int AGENT_VERSION = 0x00000002;
+    private static final int AGENT_VERSION = 0x00000003;
 
     public static void main(String[] args) {
         int exitCode = 0;
@@ -45,68 +49,70 @@
             }
 
             String commandString = args[0];
+            switch (commandString) {
+                case "dump": {
+                    if (args.length != 3) {
+                        showUsage(1);
+                    }
 
-            if (commandString.equals("extract")) {
-                if (args.length != 2) {
-                    showUsage(1);
-                }
-
-                String packageName = args[1];
-                extractMetaData(packageName);
-            } else if (commandString.equals("find")) {
-                if (args.length != 2) {
-                    showUsage(1);
-                }
-
-                String packageName = args[1];
-                if (getFilenameFromPackageName(packageName) == null) {
-                    exitCode = 3;
-                }
-            } else if (commandString.equals("apply")) {
-                if (args.length < 4) {
-                    showUsage(1);
-                }
-
-                String packageName = args[1];
-                String patchPath = args[2];
-                String outputParam = args[3];
-
-                InputStream deltaInputStream = null;
-                if (patchPath.compareTo("-") == 0) {
-                    deltaInputStream = System.in;
-                } else {
-                    deltaInputStream = new FileInputStream(patchPath);
-                }
-
-                if (outputParam.equals("-o")) {
-                    OutputStream outputStream = null;
-                    if (args.length > 4) {
-                        String outputPath = args[4];
-                        if (!outputPath.equals("-")) {
-                            outputStream = new FileOutputStream(outputPath);
+                    String requiredVersion = args[1];
+                    if (AGENT_VERSION == Integer.parseInt(requiredVersion)) {
+                        String packageName = args[2];
+                        String packagePath = getFilenameFromPackageName(packageName);
+                        if (packagePath != null) {
+                            dumpApk(packageName, packagePath);
+                        } else {
+                            exitCode = 3;
                         }
+                    } else {
+                        System.out.printf("0x%08X\n", AGENT_VERSION);
+                        exitCode = 4;
                     }
-                    if (outputStream == null) {
-                        outputStream = System.out;
-                    }
-                    File deviceFile = getFileFromPackageName(packageName);
-                    writePatchToStream(
-                            new RandomAccessFile(deviceFile, "r"), deltaInputStream, outputStream);
-                } else if (outputParam.equals("-pm")) {
-                    String[] sessionArgs = null;
-                    if (args.length > 4) {
-                        int numSessionArgs = args.length-4;
-                        sessionArgs = new String[numSessionArgs];
-                        for (int i=0 ; i<numSessionArgs ; i++) {
-                            sessionArgs[i] = args[i+4];
-                        }
-                    }
-                    exitCode = applyPatch(packageName, deltaInputStream, sessionArgs);
+                    break;
                 }
-            } else if (commandString.equals("version")) {
-                System.out.printf("0x%08X\n", AGENT_VERSION);
-            } else {
-                showUsage(1);
+                case "apply": {
+                    if (args.length < 3) {
+                        showUsage(1);
+                    }
+
+                    String patchPath = args[1];
+                    String outputParam = args[2];
+
+                    InputStream deltaInputStream = null;
+                    if (patchPath.compareTo("-") == 0) {
+                        deltaInputStream = System.in;
+                    } else {
+                        deltaInputStream = new FileInputStream(patchPath);
+                    }
+
+                    if (outputParam.equals("-o")) {
+                        OutputStream outputStream = null;
+                        if (args.length > 3) {
+                            String outputPath = args[3];
+                            if (!outputPath.equals("-")) {
+                                outputStream = new FileOutputStream(outputPath);
+                            }
+                        }
+                        if (outputStream == null) {
+                            outputStream = System.out;
+                        }
+                        writePatchToStream(deltaInputStream, outputStream);
+                    } else if (outputParam.equals("-pm")) {
+                        String[] sessionArgs = null;
+                        if (args.length > 3) {
+                            int numSessionArgs = args.length - 3;
+                            sessionArgs = new String[numSessionArgs];
+                            for (int i = 0; i < numSessionArgs; i++) {
+                                sessionArgs[i] = args[i + 3];
+                            }
+                        }
+                        exitCode = applyPatch(deltaInputStream, sessionArgs);
+                    }
+                    break;
+                }
+                default:
+                    showUsage(1);
+                    break;
             }
         } catch (Exception e) {
             System.err.println("Error: " + e);
@@ -118,16 +124,16 @@
 
     private static void showUsage(int exitCode) {
         System.err.println(
-            "usage: deployagent <command> [<args>]\n\n" +
-            "commands:\n" +
-            "version                             get the version\n" +
-            "find PKGNAME                        return zero if package found, else non-zero\n" +
-            "extract PKGNAME                     extract an installed package's metadata\n" +
-            "apply PKGNAME PATCHFILE [-o|-pm]    apply a patch from PATCHFILE (- for stdin) to an installed package\n" +
-            " -o <FILE> directs output to FILE, default or - for stdout\n" +
-            " -pm <ARGS> directs output to package manager, passes <ARGS> to 'pm install-create'\n"
-            );
-
+                "usage: deployagent <command> [<args>]\n\n" +
+                        "commands:\n" +
+                        "dump VERSION PKGNAME  dump info for an installed package given that " +
+                        "VERSION equals current agent's version\n" +
+                        "apply PATCHFILE [-o|-pm]    apply a patch from PATCHFILE " +
+                        "(- for stdin) to an installed package\n" +
+                        " -o <FILE> directs output to FILE, default or - for stdout\n" +
+                        " -pm <ARGS> directs output to package manager, passes <ARGS> to " +
+                        "'pm install-create'\n"
+        );
         System.exit(exitCode);
     }
 
@@ -162,32 +168,34 @@
                 }
                 int equalsIndex = line.lastIndexOf(packageSuffix);
                 String fileName =
-                    line.substring(packageIndex + packagePrefix.length(), equalsIndex);
+                        line.substring(packageIndex + packagePrefix.length(), equalsIndex);
                 return fileName;
             }
         }
         return null;
     }
 
-    private static File getFileFromPackageName(String packageName) throws IOException {
-        String filename = getFilenameFromPackageName(packageName);
-        if (filename == null) {
-            // Should not happen (function is only called when we know the package exists)
-            throw new IOException("package not found");
-        }
-        return new File(filename);
-    }
+    private static void dumpApk(String packageName, String packagePath) throws IOException {
+        File apk = new File(packagePath);
+        ApkArchive.Dump dump = new ApkArchive(apk).extractMetadata();
 
-    private static void extractMetaData(String packageName) throws IOException {
-        File apkFile = getFileFromPackageName(packageName);
-        APKMetaData apkMetaData = PatchUtils.getAPKMetaData(apkFile);
-        apkMetaData.writeDelimitedTo(System.out);
+        APKDump.Builder apkDumpBuilder = APKDump.newBuilder();
+        apkDumpBuilder.setName(packageName);
+        if (dump.cd != null) {
+            apkDumpBuilder.setCd(ByteString.copyFrom(dump.cd));
+        }
+        if (dump.signature != null) {
+            apkDumpBuilder.setSignature(ByteString.copyFrom(dump.signature));
+        }
+        apkDumpBuilder.setAbsolutePath(apk.getAbsolutePath());
+
+        apkDumpBuilder.build().writeTo(System.out);
     }
 
     private static int createInstallSession(String[] args) throws IOException {
         StringBuilder commandBuilder = new StringBuilder();
         commandBuilder.append("pm install-create ");
-        for (int i=0 ; args != null && i<args.length ; i++) {
+        for (int i = 0; args != null && i < args.length; i++) {
             commandBuilder.append(args[i] + " ");
         }
 
@@ -199,7 +207,8 @@
         String successLineEnd = "]";
         while ((line = reader.readLine()) != null) {
             if (line.startsWith(successLineStart) && line.endsWith(successLineEnd)) {
-                return Integer.parseInt(line.substring(successLineStart.length(), line.lastIndexOf(successLineEnd)));
+                return Integer.parseInt(line.substring(successLineStart.length(),
+                        line.lastIndexOf(successLineEnd)));
             }
         }
 
@@ -213,17 +222,15 @@
         return p.exitValue();
     }
 
-    private static int applyPatch(String packageName, InputStream deltaStream, String[] sessionArgs)
+    private static int applyPatch(InputStream deltaStream, String[] sessionArgs)
             throws IOException, PatchFormatException {
-        File deviceFile = getFileFromPackageName(packageName);
         int sessionId = createInstallSession(sessionArgs);
         if (sessionId < 0) {
             System.err.println("PM Create Session Failed");
             return -1;
         }
 
-        int writeExitCode = writePatchedDataToSession(new RandomAccessFile(deviceFile, "r"), deltaStream, sessionId);
-
+        int writeExitCode = writePatchedDataToSession(deltaStream, sessionId);
         if (writeExitCode == 0) {
             return commitInstallSession(sessionId);
         } else {
@@ -231,85 +238,94 @@
         }
     }
 
-    private static long writePatchToStream(RandomAccessFile oldData, InputStream patchData,
-        OutputStream outputStream) throws IOException, PatchFormatException {
+    private static long writePatchToStream(InputStream patchData,
+            OutputStream outputStream) throws IOException, PatchFormatException {
         long newSize = readPatchHeader(patchData);
-        long bytesWritten = writePatchedDataToStream(oldData, newSize, patchData, outputStream);
+        long bytesWritten = writePatchedDataToStream(newSize, patchData, outputStream);
         outputStream.flush();
         if (bytesWritten != newSize) {
             throw new PatchFormatException(String.format(
-                "output size mismatch (expected %ld but wrote %ld)", newSize, bytesWritten));
+                    "output size mismatch (expected %ld but wrote %ld)", newSize, bytesWritten));
         }
         return bytesWritten;
     }
 
     private static long readPatchHeader(InputStream patchData)
-        throws IOException, PatchFormatException {
+            throws IOException, PatchFormatException {
         byte[] signatureBuffer = new byte[PatchUtils.SIGNATURE.length()];
         try {
-            PatchUtils.readFully(patchData, signatureBuffer, 0, signatureBuffer.length);
+            PatchUtils.readFully(patchData, signatureBuffer);
         } catch (IOException e) {
             throw new PatchFormatException("truncated signature");
         }
 
-        String signature = new String(signatureBuffer, 0, signatureBuffer.length, "US-ASCII");
+        String signature = new String(signatureBuffer);
         if (!PatchUtils.SIGNATURE.equals(signature)) {
             throw new PatchFormatException("bad signature");
         }
 
-        long newSize = PatchUtils.readBsdiffLong(patchData);
-        if (newSize < 0 || newSize > Integer.MAX_VALUE) {
-            throw new PatchFormatException("bad newSize");
+        long newSize = PatchUtils.readLELong(patchData);
+        if (newSize < 0) {
+            throw new PatchFormatException("bad newSize: " + newSize);
         }
 
         return newSize;
     }
 
     // Note that this function assumes patchData has been seek'ed to the start of the delta stream
-    // (i.e. the signature has already been read by readPatchHeader). For a stream that points to the
-    // start of a patch file call writePatchToStream
-    private static long writePatchedDataToStream(RandomAccessFile oldData, long newSize,
-        InputStream patchData, OutputStream outputStream) throws IOException {
+    // (i.e. the signature has already been read by readPatchHeader). For a stream that points to
+    // the start of a patch file call writePatchToStream
+    private static long writePatchedDataToStream(long newSize, InputStream patchData,
+            OutputStream outputStream) throws IOException {
+        String deviceFile = PatchUtils.readString(patchData);
+        RandomAccessFile oldDataFile = new RandomAccessFile(deviceFile, "r");
+        FileChannel oldData = oldDataFile.getChannel();
+
+        WritableByteChannel newData = Channels.newChannel(outputStream);
+
         long newDataBytesWritten = 0;
         byte[] buffer = new byte[BUFFER_SIZE];
 
         while (newDataBytesWritten < newSize) {
-            long copyLen = PatchUtils.readFormattedLong(patchData);
-            if (copyLen > 0) {
-                PatchUtils.pipe(patchData, outputStream, buffer, (int) copyLen);
+            long newDataLen = PatchUtils.readLELong(patchData);
+            if (newDataLen > 0) {
+                PatchUtils.pipe(patchData, outputStream, buffer, newDataLen);
             }
 
-            long oldDataOffset = PatchUtils.readFormattedLong(patchData);
-            long oldDataLen = PatchUtils.readFormattedLong(patchData);
-            oldData.seek(oldDataOffset);
-            if (oldDataLen > 0) {
-                PatchUtils.pipe(oldData, outputStream, buffer, (int) oldDataLen);
+            long oldDataOffset = PatchUtils.readLELong(patchData);
+            long oldDataLen = PatchUtils.readLELong(patchData);
+            if (oldDataLen >= 0) {
+                long offset = oldDataOffset;
+                long len = oldDataLen;
+                while (len > 0) {
+                    long chunkLen = Math.min(len, 1024*1024*1024);
+                    oldData.transferTo(offset, chunkLen, newData);
+                    offset += chunkLen;
+                    len -= chunkLen;
+                }
             }
-
-            newDataBytesWritten += copyLen + oldDataLen;
+            newDataBytesWritten += newDataLen + oldDataLen;
         }
 
         return newDataBytesWritten;
     }
 
-    private static int writePatchedDataToSession(RandomAccessFile oldData, InputStream patchData, int sessionId)
+    private static int writePatchedDataToSession(InputStream patchData, int sessionId)
             throws IOException, PatchFormatException {
         try {
             Process p;
             long newSize = readPatchHeader(patchData);
-            StringBuilder commandBuilder = new StringBuilder();
-            commandBuilder.append(String.format("pm install-write -S %d %d -- -", newSize, sessionId));
-
-            String command = commandBuilder.toString();
+            String command = String.format("pm install-write -S %d %d -- -", newSize, sessionId);
             p = Runtime.getRuntime().exec(command);
 
             OutputStream sessionOutputStream = p.getOutputStream();
-            long bytesWritten = writePatchedDataToStream(oldData, newSize, patchData, sessionOutputStream);
+            long bytesWritten = writePatchedDataToStream(newSize, patchData, sessionOutputStream);
             sessionOutputStream.flush();
             p.waitFor();
             if (bytesWritten != newSize) {
                 throw new PatchFormatException(
-                        String.format("output size mismatch (expected %d but wrote %)", newSize, bytesWritten));
+                        String.format("output size mismatch (expected %d but wrote %)", newSize,
+                                bytesWritten));
             }
             return p.exitValue();
         } catch (InterruptedException e) {
diff --git a/adb/fastdeploy/deploylib/src/com/android/fastdeploy/PatchFormatException.java b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/PatchFormatException.java
similarity index 100%
rename from adb/fastdeploy/deploylib/src/com/android/fastdeploy/PatchFormatException.java
rename to adb/fastdeploy/deployagent/src/com/android/fastdeploy/PatchFormatException.java
diff --git a/adb/fastdeploy/deployagent/src/com/android/fastdeploy/PatchUtils.java b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/PatchUtils.java
new file mode 100644
index 0000000..54be26f
--- /dev/null
+++ b/adb/fastdeploy/deployagent/src/com/android/fastdeploy/PatchUtils.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package com.android.fastdeploy;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+class PatchUtils {
+    public static final String SIGNATURE = "FASTDEPLOY";
+
+    /**
+     * Reads a 64-bit signed integer in Little Endian format from the specified {@link
+     * DataInputStream}.
+     *
+     * @param in the stream to read from.
+     */
+    static long readLELong(InputStream in) throws IOException {
+        byte[] buffer = new byte[Long.BYTES];
+        readFully(in, buffer);
+        ByteBuffer buf = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN);
+        return buf.getLong();
+    }
+
+    static String readString(InputStream in) throws IOException {
+        int size = (int) readLELong(in);
+        byte[] buffer = new byte[size];
+        readFully(in, buffer);
+        return new String(buffer);
+    }
+
+    static void readFully(final InputStream in, final byte[] destination, final int startAt,
+            final int numBytes) throws IOException {
+        int numRead = 0;
+        while (numRead < numBytes) {
+            int readNow = in.read(destination, startAt + numRead, numBytes - numRead);
+            if (readNow == -1) {
+                throw new IOException("truncated input stream");
+            }
+            numRead += readNow;
+        }
+    }
+
+    static void readFully(final InputStream in, final byte[] destination) throws IOException {
+        readFully(in, destination, 0, destination.length);
+    }
+
+    static void pipe(final InputStream in, final OutputStream out, final byte[] buffer,
+            long copyLength) throws IOException {
+        while (copyLength > 0) {
+            int maxCopy = (int) Math.min(buffer.length, copyLength);
+            readFully(in, buffer, 0, maxCopy);
+            out.write(buffer, 0, maxCopy);
+            copyLength -= maxCopy;
+        }
+    }
+}
diff --git a/adb/fastdeploy/deployagent/test/com/android/fastdeploy/ApkArchiveTest.java b/adb/fastdeploy/deployagent/test/com/android/fastdeploy/ApkArchiveTest.java
new file mode 100644
index 0000000..7c2468f
--- /dev/null
+++ b/adb/fastdeploy/deployagent/test/com/android/fastdeploy/ApkArchiveTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package com.android.fastdeploy;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.android.fastdeploy.ApkArchive;
+
+import java.io.File;
+import java.io.IOException;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ApkArchiveTest {
+    private static final File SAMPLE_APK = new File("/data/local/tmp/FastDeployTests/sample.apk");
+    private static final File WRONG_APK = new File("/data/local/tmp/FastDeployTests/sample.cd");
+
+    @Test
+    public void testApkArchiveSizes() throws IOException {
+        ApkArchive archive = new ApkArchive(SAMPLE_APK);
+
+        ApkArchive.Location cdLoc = archive.getCDLocation();
+        assertNotEquals(cdLoc, null);
+        assertEquals(cdLoc.offset, 2044145);
+        assertEquals(cdLoc.size, 49390);
+
+        // Check that block can be retrieved
+        ApkArchive.Location sigLoc = archive.getSignatureLocation(cdLoc.offset);
+        assertNotEquals(sigLoc, null);
+        assertEquals(sigLoc.offset, 2040049);
+        assertEquals(sigLoc.size, 4088);
+    }
+
+    @Test
+    public void testApkArchiveDump() throws IOException {
+        ApkArchive archive = new ApkArchive(SAMPLE_APK);
+
+        ApkArchive.Dump dump = archive.extractMetadata();
+        assertNotEquals(dump, null);
+        assertNotEquals(dump.cd, null);
+        assertNotEquals(dump.signature, null);
+        assertEquals(dump.cd.length, 49390);
+        assertEquals(dump.signature.length, 4088);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testApkArchiveDumpWrongApk() throws IOException {
+        ApkArchive archive = new ApkArchive(WRONG_APK);
+
+        archive.extractMetadata();
+    }
+}
diff --git a/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java b/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java
new file mode 100644
index 0000000..4aa2f79
--- /dev/null
+++ b/adb/fastdeploy/deployagent/test/com/android/fastdeploy/FastDeployTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+package com.android.fastdeploy;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class FastDeployTest extends BaseHostJUnit4Test {
+
+    private static final String TEST_APP_PACKAGE = "com.example.helloworld";
+    private static final String TEST_APK5_NAME = "helloworld5.apk";
+    private static final String TEST_APK7_NAME = "helloworld7.apk";
+
+    private String mTestApk5Path;
+    private String mTestApk7Path;
+
+    @Before
+    public void setUp() throws Exception {
+        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
+        getDevice().uninstallPackage(TEST_APP_PACKAGE);
+        mTestApk5Path = buildHelper.getTestFile(TEST_APK5_NAME).getAbsolutePath();
+        mTestApk7Path = buildHelper.getTestFile(TEST_APK7_NAME).getAbsolutePath();
+    }
+
+    @Test
+    public void testAppInstalls() throws Exception {
+        fastInstallPackage(mTestApk5Path);
+        assertTrue(isAppInstalled(TEST_APP_PACKAGE));
+        getDevice().uninstallPackage(TEST_APP_PACKAGE);
+        assertFalse(isAppInstalled(TEST_APP_PACKAGE));
+    }
+
+    @Test
+    public void testAppPatch() throws Exception {
+        fastInstallPackage(mTestApk5Path);
+        assertTrue(isAppInstalled(TEST_APP_PACKAGE));
+        fastInstallPackage(mTestApk7Path);
+        assertTrue(isAppInstalled(TEST_APP_PACKAGE));
+        getDevice().uninstallPackage(TEST_APP_PACKAGE);
+        assertFalse(isAppInstalled(TEST_APP_PACKAGE));
+    }
+
+    private boolean isAppInstalled(String packageName) throws DeviceNotAvailableException {
+        final String result = getDevice().executeShellCommand("pm list packages");
+        CLog.logAndDisplay(LogLevel.INFO, result);
+        final int prefixLength = "package:".length();
+        return Arrays.stream(result.split("\\r?\\n"))
+                .anyMatch(line -> line.substring(prefixLength).equals(packageName));
+    }
+
+    // Mostly copied from PkgInstallSignatureVerificationTest.java.
+    private void fastInstallPackage(String apkPath)
+            throws IOException, DeviceNotAvailableException {
+        String result = getDevice().executeAdbCommand("install", "-t", "--fastdeploy", "--force-agent",
+                apkPath);
+        CLog.logAndDisplay(LogLevel.INFO, result);
+    }
+}
+
+
diff --git a/adb/fastdeploy/deploylib/src/com/android/fastdeploy/PatchUtils.java b/adb/fastdeploy/deploylib/src/com/android/fastdeploy/PatchUtils.java
deleted file mode 100644
index f0f00e1..0000000
--- a/adb/fastdeploy/deploylib/src/com/android/fastdeploy/PatchUtils.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.fastdeploy;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-import com.android.tools.build.apkzlib.zip.ZFile;
-import com.android.tools.build.apkzlib.zip.ZFileOptions;
-import com.android.tools.build.apkzlib.zip.StoredEntry;
-import com.android.tools.build.apkzlib.zip.StoredEntryType;
-import com.android.tools.build.apkzlib.zip.CentralDirectoryHeaderCompressInfo;
-import com.android.tools.build.apkzlib.zip.CentralDirectoryHeader;
-
-import com.android.fastdeploy.APKMetaData;
-import com.android.fastdeploy.APKEntry;
-
-class PatchUtils {
-    private static final long NEGATIVE_MASK = 1L << 63;
-    private static final long NEGATIVE_LONG_SIGN_MASK = 1L << 63;
-    public static final String SIGNATURE = "HAMADI/IHD";
-
-    private static long getOffsetFromEntry(StoredEntry entry) {
-        return entry.getCentralDirectoryHeader().getOffset() + entry.getLocalHeaderSize();
-    }
-
-    public static APKMetaData getAPKMetaData(File apkFile) throws IOException {
-        APKMetaData.Builder apkEntriesBuilder = APKMetaData.newBuilder();
-        ZFileOptions options = new ZFileOptions();
-        ZFile zFile = new ZFile(apkFile, options);
-
-        ArrayList<StoredEntry> metaDataEntries = new ArrayList<StoredEntry>();
-
-        for (StoredEntry entry : zFile.entries()) {
-            if (entry.getType() != StoredEntryType.FILE) {
-                continue;
-            }
-            metaDataEntries.add(entry);
-        }
-
-        Collections.sort(metaDataEntries, new Comparator<StoredEntry>() {
-            private long getOffsetFromEntry(StoredEntry entry) {
-                return PatchUtils.getOffsetFromEntry(entry);
-            }
-
-            @Override
-            public int compare(StoredEntry lhs, StoredEntry rhs) {
-                // -1 - less than, 1 - greater than, 0 - equal, all inversed for descending
-                return Long.compare(getOffsetFromEntry(lhs), getOffsetFromEntry(rhs));
-            }
-        });
-
-        for (StoredEntry entry : metaDataEntries) {
-            CentralDirectoryHeader cdh = entry.getCentralDirectoryHeader();
-            CentralDirectoryHeaderCompressInfo cdhci = cdh.getCompressionInfoWithWait();
-
-            APKEntry.Builder entryBuilder = APKEntry.newBuilder();
-            entryBuilder.setCrc32(cdh.getCrc32());
-            entryBuilder.setFileName(cdh.getName());
-            entryBuilder.setCompressedSize(cdhci.getCompressedSize());
-            entryBuilder.setUncompressedSize(cdh.getUncompressedSize());
-            entryBuilder.setDataOffset(getOffsetFromEntry(entry));
-
-            apkEntriesBuilder.addEntries(entryBuilder);
-            apkEntriesBuilder.build();
-        }
-        return apkEntriesBuilder.build();
-    }
-
-    /**
-     * Writes a 64-bit signed integer to the specified {@link OutputStream}. The least significant
-     * byte is written first and the most significant byte is written last.
-     * @param value the value to write
-     * @param outputStream the stream to write to
-     */
-    static void writeFormattedLong(final long value, OutputStream outputStream) throws IOException {
-        long y = value;
-        if (y < 0) {
-            y = (-y) | NEGATIVE_MASK;
-        }
-
-        for (int i = 0; i < 8; ++i) {
-            outputStream.write((byte) (y & 0xff));
-            y >>>= 8;
-        }
-    }
-
-    /**
-     * Reads a 64-bit signed integer written by {@link #writeFormattedLong(long, OutputStream)} from
-     * the specified {@link InputStream}.
-     * @param inputStream the stream to read from
-     */
-    static long readFormattedLong(InputStream inputStream) throws IOException {
-        long result = 0;
-        for (int bitshift = 0; bitshift < 64; bitshift += 8) {
-            result |= ((long) inputStream.read()) << bitshift;
-        }
-
-        if ((result - NEGATIVE_MASK) > 0) {
-            result = (result & ~NEGATIVE_MASK) * -1;
-        }
-        return result;
-    }
-
-    static final long readBsdiffLong(InputStream in) throws PatchFormatException, IOException {
-        long result = 0;
-        for (int bitshift = 0; bitshift < 64; bitshift += 8) {
-            result |= ((long) in.read()) << bitshift;
-        }
-
-        if (result == NEGATIVE_LONG_SIGN_MASK) {
-            // "Negative zero", which is valid in signed-magnitude format.
-            // NB: No sane patch generator should ever produce such a value.
-            throw new PatchFormatException("read negative zero");
-        }
-
-        if ((result & NEGATIVE_LONG_SIGN_MASK) != 0) {
-            result = -(result & ~NEGATIVE_LONG_SIGN_MASK);
-        }
-
-        return result;
-    }
-
-    static void readFully(final InputStream in, final byte[] destination, final int startAt,
-        final int numBytes) throws IOException {
-        int numRead = 0;
-        while (numRead < numBytes) {
-            int readNow = in.read(destination, startAt + numRead, numBytes - numRead);
-            if (readNow == -1) {
-                throw new IOException("truncated input stream");
-            }
-            numRead += readNow;
-        }
-    }
-
-    static void pipe(final InputStream in, final OutputStream out, final byte[] buffer,
-        long copyLength) throws IOException {
-        while (copyLength > 0) {
-            int maxCopy = Math.min(buffer.length, (int) copyLength);
-            readFully(in, buffer, 0, maxCopy);
-            out.write(buffer, 0, maxCopy);
-            copyLength -= maxCopy;
-        }
-    }
-
-    static void pipe(final RandomAccessFile in, final OutputStream out, final byte[] buffer,
-        long copyLength) throws IOException {
-        while (copyLength > 0) {
-            int maxCopy = Math.min(buffer.length, (int) copyLength);
-            in.readFully(buffer, 0, maxCopy);
-            out.write(buffer, 0, maxCopy);
-            copyLength -= maxCopy;
-        }
-    }
-
-    static void fill(byte value, final OutputStream out, final byte[] buffer, long fillLength)
-        throws IOException {
-        while (fillLength > 0) {
-            int maxCopy = Math.min(buffer.length, (int) fillLength);
-            Arrays.fill(buffer, 0, maxCopy, value);
-            out.write(buffer, 0, maxCopy);
-            fillLength -= maxCopy;
-        }
-    }
-}
diff --git a/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp b/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp
new file mode 100644
index 0000000..932d579
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/apk_archive.cpp
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+#define TRACE_TAG ADB
+
+#include "apk_archive.h"
+
+#include "adb_trace.h"
+#include "sysdeps.h"
+
+#include <android-base/endian.h>
+#include <android-base/mapped_file.h>
+
+#include <openssl/md5.h>
+
+constexpr uint16_t kCompressStored = 0;
+
+// mask value that signifies that the entry has a DD
+static const uint32_t kGPBDDFlagMask = 0x0008;
+
+namespace {
+struct FileRegion {
+    FileRegion(borrowed_fd fd, off64_t offset, size_t length)
+        : mapped_(android::base::MappedFile::FromOsHandle(adb_get_os_handle(fd), offset, length,
+                                                          PROT_READ)) {
+        if (mapped_ != nullptr) {
+            return;
+        }
+
+        // Mapped file failed, falling back to pread.
+        buffer_.resize(length);
+        if (auto err = adb_pread(fd.get(), buffer_.data(), length, offset); size_t(err) != length) {
+            fprintf(stderr, "Unable to read %lld bytes at offset %" PRId64 " \n",
+                    static_cast<long long>(length), offset);
+            buffer_.clear();
+            return;
+        }
+    }
+
+    const char* data() const { return mapped_ ? mapped_->data() : buffer_.data(); }
+    size_t size() const { return mapped_ ? mapped_->size() : buffer_.size(); }
+
+  private:
+    FileRegion() = default;
+    DISALLOW_COPY_AND_ASSIGN(FileRegion);
+
+    std::unique_ptr<android::base::MappedFile> mapped_;
+    std::string buffer_;
+};
+}  // namespace
+
+using com::android::fastdeploy::APKDump;
+
+ApkArchive::ApkArchive(const std::string& path) : path_(path), size_(0) {
+    fd_.reset(adb_open(path_.c_str(), O_RDONLY));
+    if (fd_ == -1) {
+        fprintf(stderr, "Unable to open file '%s'\n", path_.c_str());
+        return;
+    }
+
+    struct stat st;
+    if (stat(path_.c_str(), &st) == -1) {
+        fprintf(stderr, "Unable to stat file '%s'\n", path_.c_str());
+        return;
+    }
+    size_ = st.st_size;
+}
+
+ApkArchive::~ApkArchive() {}
+
+APKDump ApkArchive::ExtractMetadata() {
+    D("ExtractMetadata");
+    if (!ready()) {
+        return {};
+    }
+
+    Location cdLoc = GetCDLocation();
+    if (!cdLoc.valid) {
+        return {};
+    }
+
+    APKDump dump;
+    dump.set_absolute_path(path_);
+    dump.set_cd(ReadMetadata(cdLoc));
+
+    Location sigLoc = GetSignatureLocation(cdLoc.offset);
+    if (sigLoc.valid) {
+        dump.set_signature(ReadMetadata(sigLoc));
+    }
+    return dump;
+}
+
+off_t ApkArchive::FindEndOfCDRecord() const {
+    constexpr int endOfCDSignature = 0x06054b50;
+    constexpr off_t endOfCDMinSize = 22;
+    constexpr off_t endOfCDMaxSize = 65535 + endOfCDMinSize;
+
+    auto sizeToRead = std::min(size_, endOfCDMaxSize);
+    auto readOffset = size_ - sizeToRead;
+    FileRegion mapped(fd_, readOffset, sizeToRead);
+
+    // Start scanning from the end
+    auto* start = mapped.data();
+    auto* cursor = start + mapped.size() - sizeof(endOfCDSignature);
+
+    // Search for End of Central Directory record signature.
+    while (cursor >= start) {
+        if (*(int32_t*)cursor == endOfCDSignature) {
+            return readOffset + (cursor - start);
+        }
+        cursor--;
+    }
+    return -1;
+}
+
+ApkArchive::Location ApkArchive::FindCDRecord(const char* cursor) {
+    struct ecdr_t {
+        int32_t signature;
+        uint16_t diskNumber;
+        uint16_t numDisk;
+        uint16_t diskEntries;
+        uint16_t numEntries;
+        uint32_t crSize;
+        uint32_t offsetToCdHeader;
+        uint16_t commentSize;
+        uint8_t comment[0];
+    } __attribute__((packed));
+    ecdr_t* header = (ecdr_t*)cursor;
+
+    Location location;
+    location.offset = header->offsetToCdHeader;
+    location.size = header->crSize;
+    location.valid = true;
+    return location;
+}
+
+ApkArchive::Location ApkArchive::GetCDLocation() {
+    constexpr off_t cdEntryHeaderSizeBytes = 22;
+    Location location;
+
+    // Find End of Central Directory Record
+    off_t eocdRecord = FindEndOfCDRecord();
+    if (eocdRecord < 0) {
+        fprintf(stderr, "Unable to find End of Central Directory record in file '%s'\n",
+                path_.c_str());
+        return location;
+    }
+
+    // Find Central Directory Record
+    FileRegion mapped(fd_, eocdRecord, cdEntryHeaderSizeBytes);
+    location = FindCDRecord(mapped.data());
+    if (!location.valid) {
+        fprintf(stderr, "Unable to find Central Directory File Header in file '%s'\n",
+                path_.c_str());
+        return location;
+    }
+
+    return location;
+}
+
+ApkArchive::Location ApkArchive::GetSignatureLocation(off_t cdRecordOffset) {
+    Location location;
+
+    // Signature constants.
+    constexpr off_t endOfSignatureSize = 24;
+    off_t signatureOffset = cdRecordOffset - endOfSignatureSize;
+    if (signatureOffset < 0) {
+        fprintf(stderr, "Unable to find signature in file '%s'\n", path_.c_str());
+        return location;
+    }
+
+    FileRegion mapped(fd_, signatureOffset, endOfSignatureSize);
+
+    uint64_t signatureSize = *(uint64_t*)mapped.data();
+    auto* signature = mapped.data() + sizeof(signatureSize);
+    // Check if there is a v2/v3 Signature block here.
+    if (memcmp(signature, "APK Sig Block 42", 16)) {
+        return location;
+    }
+
+    // This is likely a signature block.
+    location.size = signatureSize;
+    location.offset = cdRecordOffset - location.size - 8;
+    location.valid = true;
+
+    return location;
+}
+
+std::string ApkArchive::ReadMetadata(Location loc) const {
+    FileRegion mapped(fd_, loc.offset, loc.size);
+    return {mapped.data(), mapped.size()};
+}
+
+size_t ApkArchive::ParseCentralDirectoryRecord(const char* input, size_t size, std::string* md5Hash,
+                                               int64_t* localFileHeaderOffset, int64_t* dataSize) {
+    // A structure representing the fixed length fields for a single
+    // record in the central directory of the archive. In addition to
+    // the fixed length fields listed here, each central directory
+    // record contains a variable length "file_name" and "extra_field"
+    // whose lengths are given by |file_name_length| and |extra_field_length|
+    // respectively.
+    static constexpr int kCDFileHeaderMagic = 0x02014b50;
+    struct CentralDirectoryRecord {
+        // The start of record signature. Must be |kSignature|.
+        uint32_t record_signature;
+        // Source tool version. Top byte gives source OS.
+        uint16_t version_made_by;
+        // Tool version. Ignored by this implementation.
+        uint16_t version_needed;
+        // The "general purpose bit flags" for this entry. The only
+        // flag value that we currently check for is the "data descriptor"
+        // flag.
+        uint16_t gpb_flags;
+        // The compression method for this entry, one of |kCompressStored|
+        // and |kCompressDeflated|.
+        uint16_t compression_method;
+        // The file modification time and date for this entry.
+        uint16_t last_mod_time;
+        uint16_t last_mod_date;
+        // The CRC-32 checksum for this entry.
+        uint32_t crc32;
+        // The compressed size (in bytes) of this entry.
+        uint32_t compressed_size;
+        // The uncompressed size (in bytes) of this entry.
+        uint32_t uncompressed_size;
+        // The length of the entry file name in bytes. The file name
+        // will appear immediately after this record.
+        uint16_t file_name_length;
+        // The length of the extra field info (in bytes). This data
+        // will appear immediately after the entry file name.
+        uint16_t extra_field_length;
+        // The length of the entry comment (in bytes). This data will
+        // appear immediately after the extra field.
+        uint16_t comment_length;
+        // The start disk for this entry. Ignored by this implementation).
+        uint16_t file_start_disk;
+        // File attributes. Ignored by this implementation.
+        uint16_t internal_file_attributes;
+        // File attributes. For archives created on Unix, the top bits are the
+        // mode.
+        uint32_t external_file_attributes;
+        // The offset to the local file header for this entry, from the
+        // beginning of this archive.
+        uint32_t local_file_header_offset;
+
+      private:
+        CentralDirectoryRecord() = default;
+        DISALLOW_COPY_AND_ASSIGN(CentralDirectoryRecord);
+    } __attribute__((packed));
+
+    const CentralDirectoryRecord* cdr;
+    if (size < sizeof(*cdr)) {
+        return 0;
+    }
+
+    auto begin = input;
+    cdr = reinterpret_cast<const CentralDirectoryRecord*>(begin);
+    if (cdr->record_signature != kCDFileHeaderMagic) {
+        fprintf(stderr, "Invalid Central Directory Record signature\n");
+        return 0;
+    }
+    auto end = begin + sizeof(*cdr) + cdr->file_name_length + cdr->extra_field_length +
+               cdr->comment_length;
+
+    uint8_t md5Digest[MD5_DIGEST_LENGTH];
+    MD5((const unsigned char*)begin, end - begin, md5Digest);
+    md5Hash->assign((const char*)md5Digest, sizeof(md5Digest));
+
+    *localFileHeaderOffset = cdr->local_file_header_offset;
+    *dataSize = (cdr->compression_method == kCompressStored) ? cdr->uncompressed_size
+                                                             : cdr->compressed_size;
+
+    return end - begin;
+}
+
+size_t ApkArchive::CalculateLocalFileEntrySize(int64_t localFileHeaderOffset,
+                                               int64_t dataSize) const {
+    // The local file header for a given entry. This duplicates information
+    // present in the central directory of the archive. It is an error for
+    // the information here to be different from the central directory
+    // information for a given entry.
+    static constexpr int kLocalFileHeaderMagic = 0x04034b50;
+    struct LocalFileHeader {
+        // The local file header signature, must be |kSignature|.
+        uint32_t lfh_signature;
+        // Tool version. Ignored by this implementation.
+        uint16_t version_needed;
+        // The "general purpose bit flags" for this entry. The only
+        // flag value that we currently check for is the "data descriptor"
+        // flag.
+        uint16_t gpb_flags;
+        // The compression method for this entry, one of |kCompressStored|
+        // and |kCompressDeflated|.
+        uint16_t compression_method;
+        // The file modification time and date for this entry.
+        uint16_t last_mod_time;
+        uint16_t last_mod_date;
+        // The CRC-32 checksum for this entry.
+        uint32_t crc32;
+        // The compressed size (in bytes) of this entry.
+        uint32_t compressed_size;
+        // The uncompressed size (in bytes) of this entry.
+        uint32_t uncompressed_size;
+        // The length of the entry file name in bytes. The file name
+        // will appear immediately after this record.
+        uint16_t file_name_length;
+        // The length of the extra field info (in bytes). This data
+        // will appear immediately after the entry file name.
+        uint16_t extra_field_length;
+
+      private:
+        LocalFileHeader() = default;
+        DISALLOW_COPY_AND_ASSIGN(LocalFileHeader);
+    } __attribute__((packed));
+    static constexpr int kLocalFileHeaderSize = sizeof(LocalFileHeader);
+    CHECK(ready()) << path_;
+
+    const LocalFileHeader* lfh;
+    if (localFileHeaderOffset + kLocalFileHeaderSize > size_) {
+        fprintf(stderr,
+                "Invalid Local File Header offset in file '%s' at offset %lld, file size %lld\n",
+                path_.c_str(), static_cast<long long>(localFileHeaderOffset),
+                static_cast<long long>(size_));
+        return 0;
+    }
+
+    FileRegion lfhMapped(fd_, localFileHeaderOffset, sizeof(LocalFileHeader));
+    lfh = reinterpret_cast<const LocalFileHeader*>(lfhMapped.data());
+    if (lfh->lfh_signature != kLocalFileHeaderMagic) {
+        fprintf(stderr, "Invalid Local File Header signature in file '%s' at offset %lld\n",
+                path_.c_str(), static_cast<long long>(localFileHeaderOffset));
+        return 0;
+    }
+
+    // The *optional* data descriptor start signature.
+    static constexpr int kOptionalDataDescriptorMagic = 0x08074b50;
+    struct DataDescriptor {
+        // CRC-32 checksum of the entry.
+        uint32_t crc32;
+        // Compressed size of the entry.
+        uint32_t compressed_size;
+        // Uncompressed size of the entry.
+        uint32_t uncompressed_size;
+
+      private:
+        DataDescriptor() = default;
+        DISALLOW_COPY_AND_ASSIGN(DataDescriptor);
+    } __attribute__((packed));
+    static constexpr int kDataDescriptorSize = sizeof(DataDescriptor);
+
+    off_t ddOffset = localFileHeaderOffset + kLocalFileHeaderSize + lfh->file_name_length +
+                     lfh->extra_field_length + dataSize;
+    int64_t ddSize = 0;
+
+    int64_t localDataSize;
+    if (lfh->gpb_flags & kGPBDDFlagMask) {
+        // There is trailing data descriptor.
+        const DataDescriptor* dd;
+
+        if (ddOffset + int(sizeof(uint32_t)) > size_) {
+            fprintf(stderr,
+                    "Error reading trailing data descriptor signature in file '%s' at offset %lld, "
+                    "file size %lld\n",
+                    path_.c_str(), static_cast<long long>(ddOffset), static_cast<long long>(size_));
+            return 0;
+        }
+
+        FileRegion ddMapped(fd_, ddOffset, sizeof(uint32_t) + sizeof(DataDescriptor));
+
+        off_t localDDOffset = 0;
+        if (kOptionalDataDescriptorMagic == *(uint32_t*)ddMapped.data()) {
+            ddOffset += sizeof(uint32_t);
+            localDDOffset += sizeof(uint32_t);
+            ddSize += sizeof(uint32_t);
+        }
+        if (ddOffset + kDataDescriptorSize > size_) {
+            fprintf(stderr,
+                    "Error reading trailing data descriptor in file '%s' at offset %lld, file size "
+                    "%lld\n",
+                    path_.c_str(), static_cast<long long>(ddOffset), static_cast<long long>(size_));
+            return 0;
+        }
+
+        dd = reinterpret_cast<const DataDescriptor*>(ddMapped.data() + localDDOffset);
+        localDataSize = (lfh->compression_method == kCompressStored) ? dd->uncompressed_size
+                                                                     : dd->compressed_size;
+        ddSize += sizeof(*dd);
+    } else {
+        localDataSize = (lfh->compression_method == kCompressStored) ? lfh->uncompressed_size
+                                                                     : lfh->compressed_size;
+    }
+    if (localDataSize != dataSize) {
+        fprintf(stderr,
+                "Data sizes mismatch in file '%s' at offset %lld, CDr: %lld vs LHR/DD: %lld\n",
+                path_.c_str(), static_cast<long long>(localFileHeaderOffset),
+                static_cast<long long>(dataSize), static_cast<long long>(localDataSize));
+        return 0;
+    }
+
+    return kLocalFileHeaderSize + lfh->file_name_length + lfh->extra_field_length + dataSize +
+           ddSize;
+}
diff --git a/adb/fastdeploy/deploypatchgenerator/apk_archive.h b/adb/fastdeploy/deploypatchgenerator/apk_archive.h
new file mode 100644
index 0000000..7127800
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/apk_archive.h
@@ -0,0 +1,80 @@
+/*
+ * 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 <memory>
+#include <string>
+#include <vector>
+
+#include <adb_unique_fd.h>
+
+#include "fastdeploy/proto/ApkEntry.pb.h"
+
+class ApkArchiveTester;
+
+// Manipulates an APK archive. Process it by mmaping it in order to minimize
+// I/Os.
+class ApkArchive {
+  public:
+    friend ApkArchiveTester;
+
+    // A convenience struct to store the result of search operation when
+    // locating the EoCDr, CDr, and Signature Block.
+    struct Location {
+        off_t offset = 0;
+        off_t size = 0;
+        bool valid = false;
+    };
+
+    ApkArchive(const std::string& path);
+    ~ApkArchive();
+
+    com::android::fastdeploy::APKDump ExtractMetadata();
+
+    // Parses the CDr starting from |input| and returns number of bytes consumed.
+    // Extracts local file header offset, data size and calculates MD5 hash of the record.
+    // 0 indicates invalid CDr.
+    static size_t ParseCentralDirectoryRecord(const char* input, size_t size, std::string* md5Hash,
+                                              int64_t* localFileHeaderOffset, int64_t* dataSize);
+    // Calculates Local File Entry size including header using offset and data size from CDr.
+    // 0 indicates invalid Local File Entry.
+    size_t CalculateLocalFileEntrySize(int64_t localFileHeaderOffset, int64_t dataSize) const;
+
+  private:
+    std::string ReadMetadata(Location loc) const;
+
+    // Retrieve the location of the Central Directory Record.
+    Location GetCDLocation();
+
+    // Retrieve the location of the signature block starting from Central
+    // Directory Record
+    Location GetSignatureLocation(off_t cdRecordOffset);
+
+    // Find the End of Central Directory Record, starting from the end of the
+    // file.
+    off_t FindEndOfCDRecord() const;
+
+    // Find Central Directory Record, starting from the end of the file.
+    Location FindCDRecord(const char* cursor);
+
+    // Checks if the archive can be used.
+    bool ready() const { return fd_ >= 0; }
+
+    std::string path_;
+    off_t size_;
+    unique_fd fd_;
+};
diff --git a/adb/fastdeploy/deploypatchgenerator/apk_archive_test.cpp b/adb/fastdeploy/deploypatchgenerator/apk_archive_test.cpp
new file mode 100644
index 0000000..554cb57
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/apk_archive_test.cpp
@@ -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.
+ */
+
+#include <iostream>
+
+#include <gtest/gtest.h>
+
+#include "apk_archive.h"
+
+// Friend test to get around private scope of ApkArchive private functions.
+class ApkArchiveTester {
+  public:
+    ApkArchiveTester(const std::string& path) : archive_(path) {}
+
+    bool ready() { return archive_.ready(); }
+
+    auto ExtractMetadata() { return archive_.ExtractMetadata(); }
+
+    ApkArchive::Location GetCDLocation() { return archive_.GetCDLocation(); }
+    ApkArchive::Location GetSignatureLocation(size_t start) {
+        return archive_.GetSignatureLocation(start);
+    }
+
+  private:
+    ApkArchive archive_;
+};
+
+TEST(ApkArchiveTest, TestApkArchiveSizes) {
+    ApkArchiveTester archiveTester("fastdeploy/testdata/sample.apk");
+    EXPECT_TRUE(archiveTester.ready());
+
+    ApkArchive::Location cdLoc = archiveTester.GetCDLocation();
+    EXPECT_TRUE(cdLoc.valid);
+    ASSERT_EQ(cdLoc.offset, 2044145u);
+    ASSERT_EQ(cdLoc.size, 49390u);
+
+    // Check that block can be retrieved
+    ApkArchive::Location sigLoc = archiveTester.GetSignatureLocation(cdLoc.offset);
+    EXPECT_TRUE(sigLoc.valid);
+    ASSERT_EQ(sigLoc.offset, 2040049u);
+    ASSERT_EQ(sigLoc.size, 4088u);
+}
+
+TEST(ApkArchiveTest, TestApkArchiveDump) {
+    ApkArchiveTester archiveTester("fastdeploy/testdata/sample.apk");
+    EXPECT_TRUE(archiveTester.ready());
+
+    auto dump = archiveTester.ExtractMetadata();
+    ASSERT_EQ(dump.cd().size(), 49390u);
+    ASSERT_EQ(dump.signature().size(), 4088u);
+}
+
+TEST(ApkArchiveTest, WrongApk) {
+    ApkArchiveTester archiveTester("fastdeploy/testdata/sample.cd");
+    EXPECT_TRUE(archiveTester.ready());
+
+    auto dump = archiveTester.ExtractMetadata();
+    ASSERT_EQ(dump.cd().size(), 0u);
+    ASSERT_EQ(dump.signature().size(), 0u);
+}
diff --git a/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator.cpp b/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator.cpp
new file mode 100644
index 0000000..8aa7da7
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator.cpp
@@ -0,0 +1,255 @@
+/*
+ * 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 "deploy_patch_generator.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <algorithm>
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#include <openssl/md5.h>
+
+#include "adb_unique_fd.h"
+#include "adb_utils.h"
+#include "android-base/file.h"
+#include "patch_utils.h"
+#include "sysdeps.h"
+
+using namespace com::android::fastdeploy;
+
+void DeployPatchGenerator::Log(const char* fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    printf("\n");
+    va_end(ap);
+}
+
+static std::string HexEncode(const void* in_buffer, unsigned int size) {
+    static const char kHexChars[] = "0123456789ABCDEF";
+
+    // Each input byte creates two output hex characters.
+    std::string out_buffer(size * 2, '\0');
+
+    for (unsigned int i = 0; i < size; ++i) {
+        char byte = ((const uint8_t*)in_buffer)[i];
+        out_buffer[(i << 1)] = kHexChars[(byte >> 4) & 0xf];
+        out_buffer[(i << 1) + 1] = kHexChars[byte & 0xf];
+    }
+    return out_buffer;
+}
+
+void DeployPatchGenerator::APKEntryToLog(const APKEntry& entry) {
+    if (!is_verbose_) {
+        return;
+    }
+    Log("MD5: %s", HexEncode(entry.md5().data(), entry.md5().size()).c_str());
+    Log("Data Offset: %" PRId64, entry.dataoffset());
+    Log("Data Size: %" PRId64, entry.datasize());
+}
+
+void DeployPatchGenerator::APKMetaDataToLog(const APKMetaData& metadata) {
+    if (!is_verbose_) {
+        return;
+    }
+    Log("APK Metadata: %s", metadata.absolute_path().c_str());
+    for (int i = 0; i < metadata.entries_size(); i++) {
+        const APKEntry& entry = metadata.entries(i);
+        APKEntryToLog(entry);
+    }
+}
+
+void DeployPatchGenerator::ReportSavings(const std::vector<SimpleEntry>& identicalEntries,
+                                         uint64_t totalSize) {
+    uint64_t totalEqualBytes = 0;
+    uint64_t totalEqualFiles = 0;
+    for (size_t i = 0; i < identicalEntries.size(); i++) {
+        if (identicalEntries[i].deviceEntry != nullptr) {
+            totalEqualBytes += identicalEntries[i].localEntry->datasize();
+            totalEqualFiles++;
+        }
+    }
+    double savingPercent = (totalEqualBytes * 100.0f) / totalSize;
+    fprintf(stderr, "Detected %" PRIu64 " equal APK entries\n", totalEqualFiles);
+    fprintf(stderr, "%" PRIu64 " bytes are equal out of %" PRIu64 " (%.2f%%)\n", totalEqualBytes,
+            totalSize, savingPercent);
+}
+
+struct PatchEntry {
+    int64_t deltaFromDeviceDataStart = 0;
+    int64_t deviceDataOffset = 0;
+    int64_t deviceDataLength = 0;
+};
+static void WritePatchEntry(const PatchEntry& patchEntry, borrowed_fd input, borrowed_fd output,
+                            size_t* realSizeOut) {
+    if (!(patchEntry.deltaFromDeviceDataStart | patchEntry.deviceDataOffset |
+          patchEntry.deviceDataLength)) {
+        return;
+    }
+
+    PatchUtils::WriteLong(patchEntry.deltaFromDeviceDataStart, output);
+    if (patchEntry.deltaFromDeviceDataStart > 0) {
+        PatchUtils::Pipe(input, output, patchEntry.deltaFromDeviceDataStart);
+    }
+    auto hostDataLength = patchEntry.deviceDataLength;
+    adb_lseek(input, hostDataLength, SEEK_CUR);
+
+    PatchUtils::WriteLong(patchEntry.deviceDataOffset, output);
+    PatchUtils::WriteLong(patchEntry.deviceDataLength, output);
+
+    *realSizeOut += patchEntry.deltaFromDeviceDataStart + hostDataLength;
+}
+
+void DeployPatchGenerator::GeneratePatch(const std::vector<SimpleEntry>& entriesToUseOnDevice,
+                                         const std::string& localApkPath,
+                                         const std::string& deviceApkPath, borrowed_fd output) {
+    unique_fd input(adb_open(localApkPath.c_str(), O_RDONLY | O_CLOEXEC));
+    size_t newApkSize = adb_lseek(input, 0L, SEEK_END);
+    adb_lseek(input, 0L, SEEK_SET);
+
+    // Header.
+    PatchUtils::WriteSignature(output);
+    PatchUtils::WriteLong(newApkSize, output);
+    PatchUtils::WriteString(deviceApkPath, output);
+
+    size_t currentSizeOut = 0;
+    size_t realSizeOut = 0;
+    // Write data from the host upto the first entry we have that matches a device entry. Then write
+    // the metadata about the device entry and repeat for all entries that match on device. Finally
+    // write out any data left. If the device and host APKs are exactly the same this ends up
+    // writing out zip metadata from the local APK followed by offsets to the data to use from the
+    // device APK.
+    PatchEntry patchEntry;
+    for (size_t i = 0, size = entriesToUseOnDevice.size(); i < size; ++i) {
+        auto&& entry = entriesToUseOnDevice[i];
+        int64_t hostDataOffset = entry.localEntry->dataoffset();
+        int64_t hostDataLength = entry.localEntry->datasize();
+        int64_t deviceDataOffset = entry.deviceEntry->dataoffset();
+        // Both entries are the same, using host data length.
+        int64_t deviceDataLength = hostDataLength;
+
+        int64_t deltaFromDeviceDataStart = hostDataOffset - currentSizeOut;
+        if (deltaFromDeviceDataStart > 0) {
+            WritePatchEntry(patchEntry, input, output, &realSizeOut);
+            patchEntry.deltaFromDeviceDataStart = deltaFromDeviceDataStart;
+            patchEntry.deviceDataOffset = deviceDataOffset;
+            patchEntry.deviceDataLength = deviceDataLength;
+        } else {
+            patchEntry.deviceDataLength += deviceDataLength;
+        }
+
+        currentSizeOut += deltaFromDeviceDataStart + hostDataLength;
+    }
+    WritePatchEntry(patchEntry, input, output, &realSizeOut);
+    if (realSizeOut != currentSizeOut) {
+        fprintf(stderr, "Size mismatch current %lld vs real %lld\n",
+                static_cast<long long>(currentSizeOut), static_cast<long long>(realSizeOut));
+        error_exit("Aborting");
+    }
+
+    if (newApkSize > currentSizeOut) {
+        PatchUtils::WriteLong(newApkSize - currentSizeOut, output);
+        PatchUtils::Pipe(input, output, newApkSize - currentSizeOut);
+        PatchUtils::WriteLong(0, output);
+        PatchUtils::WriteLong(0, output);
+    }
+}
+
+bool DeployPatchGenerator::CreatePatch(const char* localApkPath, APKMetaData deviceApkMetadata,
+                                       android::base::borrowed_fd output) {
+    return CreatePatch(PatchUtils::GetHostAPKMetaData(localApkPath), std::move(deviceApkMetadata),
+                       output);
+}
+
+bool DeployPatchGenerator::CreatePatch(APKMetaData localApkMetadata, APKMetaData deviceApkMetadata,
+                                       borrowed_fd output) {
+    // Log metadata info.
+    APKMetaDataToLog(deviceApkMetadata);
+    APKMetaDataToLog(localApkMetadata);
+
+    const std::string localApkPath = localApkMetadata.absolute_path();
+    const std::string deviceApkPath = deviceApkMetadata.absolute_path();
+
+    std::vector<SimpleEntry> identicalEntries;
+    uint64_t totalSize =
+            BuildIdenticalEntries(identicalEntries, localApkMetadata, deviceApkMetadata);
+    ReportSavings(identicalEntries, totalSize);
+    GeneratePatch(identicalEntries, localApkPath, deviceApkPath, output);
+
+    return true;
+}
+
+uint64_t DeployPatchGenerator::BuildIdenticalEntries(std::vector<SimpleEntry>& outIdenticalEntries,
+                                                     const APKMetaData& localApkMetadata,
+                                                     const APKMetaData& deviceApkMetadata) {
+    outIdenticalEntries.reserve(
+            std::min(localApkMetadata.entries_size(), deviceApkMetadata.entries_size()));
+
+    using md5Digest = std::pair<uint64_t, uint64_t>;
+    struct md5Hash {
+        size_t operator()(const md5Digest& digest) const {
+            std::hash<uint64_t> hasher;
+            size_t seed = 0;
+            seed ^= hasher(digest.first) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+            seed ^= hasher(digest.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+            return seed;
+        }
+    };
+    static_assert(sizeof(md5Digest) == MD5_DIGEST_LENGTH);
+    std::unordered_map<md5Digest, std::vector<const APKEntry*>, md5Hash> deviceEntries;
+    for (const auto& deviceEntry : deviceApkMetadata.entries()) {
+        md5Digest md5;
+        memcpy(&md5, deviceEntry.md5().data(), deviceEntry.md5().size());
+
+        deviceEntries[md5].push_back(&deviceEntry);
+    }
+
+    uint64_t totalSize = 0;
+    for (const auto& localEntry : localApkMetadata.entries()) {
+        totalSize += localEntry.datasize();
+
+        md5Digest md5;
+        memcpy(&md5, localEntry.md5().data(), localEntry.md5().size());
+
+        auto deviceEntriesIt = deviceEntries.find(md5);
+        if (deviceEntriesIt == deviceEntries.end()) {
+            continue;
+        }
+
+        for (const auto* deviceEntry : deviceEntriesIt->second) {
+            if (deviceEntry->md5() == localEntry.md5()) {
+                SimpleEntry simpleEntry;
+                simpleEntry.localEntry = &localEntry;
+                simpleEntry.deviceEntry = deviceEntry;
+                APKEntryToLog(localEntry);
+                outIdenticalEntries.push_back(simpleEntry);
+                break;
+            }
+        }
+    }
+    std::sort(outIdenticalEntries.begin(), outIdenticalEntries.end(),
+              [](const SimpleEntry& lhs, const SimpleEntry& rhs) {
+                  return lhs.localEntry->dataoffset() < rhs.localEntry->dataoffset();
+              });
+    return totalSize;
+}
diff --git a/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator.h b/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator.h
new file mode 100644
index 0000000..fd7eaee
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <vector>
+
+#include "adb_unique_fd.h"
+#include "fastdeploy/proto/ApkEntry.pb.h"
+
+/**
+ * This class is responsible for creating a patch that can be accepted by the deployagent. The
+ * patch format is documented in GeneratePatch.
+ */
+class DeployPatchGenerator {
+  public:
+    using APKEntry = com::android::fastdeploy::APKEntry;
+    using APKMetaData = com::android::fastdeploy::APKMetaData;
+
+    /**
+     * Simple struct to hold mapping between local metadata and device metadata.
+     */
+    struct SimpleEntry {
+        const APKEntry* localEntry;
+        const APKEntry* deviceEntry;
+    };
+
+    /**
+     * If |is_verbose| is true ApkEntries that are similar between device and host are written to
+     * the console.
+     */
+    explicit DeployPatchGenerator(bool is_verbose) : is_verbose_(is_verbose) {}
+    /**
+     * Given a |localApkPath|, and the |deviceApkMetadata| from an installed APK this function
+     * writes a patch to the given |output|.
+     */
+    bool CreatePatch(const char* localApkPath, APKMetaData deviceApkMetadata,
+                     android::base::borrowed_fd output);
+
+  private:
+    bool is_verbose_;
+
+    /**
+     * Log function only logs data to stdout when |is_verbose_| is true.
+     */
+    void Log(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
+
+    /**
+     * Helper function to log the APKMetaData structure. If |is_verbose_| is false this function
+     * early outs. This function is used for debugging / information.
+     */
+    void APKMetaDataToLog(const APKMetaData& metadata);
+    /**
+     * Helper function to log APKEntry.
+     */
+    void APKEntryToLog(const APKEntry& entry);
+
+    /**
+     * Given the |localApkMetadata| metadata, and the |deviceApkMetadata| from an installed APK this
+     * function writes a patch to the given |output|.
+     */
+    bool CreatePatch(APKMetaData localApkMetadata, APKMetaData deviceApkMetadata,
+                     android::base::borrowed_fd output);
+
+    /**
+     * Helper function to report savings by fastdeploy. This function prints out savings even with
+     * |is_verbose_| set to false. |totalSize| is used to show a percentage of savings. Note:
+     * |totalSize| is the size of the ZipEntries. Not the size of the entire file. The metadata of
+     * the zip data needs to be sent across with every iteration.
+     * [Patch format]
+     * |Fixed String| Signature
+     * |long|         New Size of Apk
+     * |Packets[]|    Array of Packets
+     *
+     * [Packet Format]
+     * |long|     Size of data to use from patch
+     * |byte[]|   Patch data
+     * |long|     Offset of data to use already on device
+     * |long|     Length of data to read from device APK
+     * TODO(b/138306784): Move the patch format to a proto.
+     */
+    void ReportSavings(const std::vector<SimpleEntry>& identicalEntries, uint64_t totalSize);
+
+    /**
+     * This enumerates each entry in |entriesToUseOnDevice| and builds a patch file copying data
+     * from |localApkPath| where we are unable to use entries already on the device. The new patch
+     * is written to |output|. The entries are expected to be sorted by data offset from lowest to
+     * highest.
+     */
+    void GeneratePatch(const std::vector<SimpleEntry>& entriesToUseOnDevice,
+                       const std::string& localApkPath, const std::string& deviceApkPath,
+                       android::base::borrowed_fd output);
+
+  protected:
+    uint64_t BuildIdenticalEntries(std::vector<SimpleEntry>& outIdenticalEntries,
+                                   const APKMetaData& localApkMetadata,
+                                   const APKMetaData& deviceApkMetadata);
+};
diff --git a/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator_test.cpp b/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator_test.cpp
new file mode 100644
index 0000000..e4c96ea
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/deploy_patch_generator_test.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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 "deploy_patch_generator.h"
+#include "apk_archive.h"
+#include "patch_utils.h"
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+#include "sysdeps.h"
+
+using namespace com::android::fastdeploy;
+
+static std::string GetTestFile(const std::string& name) {
+    return "fastdeploy/testdata/" + name;
+}
+
+struct TestPatchGenerator : DeployPatchGenerator {
+    using DeployPatchGenerator::BuildIdenticalEntries;
+    using DeployPatchGenerator::DeployPatchGenerator;
+};
+
+TEST(DeployPatchGeneratorTest, IdenticalFileEntries) {
+    std::string apkPath = GetTestFile("rotating_cube-release.apk");
+    APKMetaData metadataA = PatchUtils::GetHostAPKMetaData(apkPath.c_str());
+    TestPatchGenerator generator(false);
+    std::vector<DeployPatchGenerator::SimpleEntry> entries;
+    generator.BuildIdenticalEntries(entries, metadataA, metadataA);
+    // Expect the entry count to match the number of entries in the metadata.
+    const uint32_t identicalCount = entries.size();
+    const uint32_t entriesCount = metadataA.entries_size();
+    EXPECT_EQ(identicalCount, entriesCount);
+}
+
+TEST(DeployPatchGeneratorTest, NoDeviceMetadata) {
+    std::string apkPath = GetTestFile("rotating_cube-release.apk");
+    // Get size of our test apk.
+    long apkSize = 0;
+    {
+        unique_fd apkFile(adb_open(apkPath.c_str(), O_RDWR));
+        apkSize = adb_lseek(apkFile, 0L, SEEK_END);
+    }
+
+    // Create a patch that is 100% different.
+    TemporaryFile output;
+    DeployPatchGenerator generator(true);
+    generator.CreatePatch(apkPath.c_str(), {}, output.fd);
+
+    // Expect a patch file that has a size at least the size of our initial APK.
+    long patchSize = adb_lseek(output.fd, 0L, SEEK_END);
+    EXPECT_GT(patchSize, apkSize);
+}
+
+TEST(DeployPatchGeneratorTest, ZeroSizePatch) {
+    std::string apkPath = GetTestFile("rotating_cube-release.apk");
+    ApkArchive archive(apkPath);
+    auto dump = archive.ExtractMetadata();
+    EXPECT_NE(dump.cd().size(), 0u);
+
+    APKMetaData metadata = PatchUtils::GetDeviceAPKMetaData(dump);
+
+    // Create a patch that is 100% the same.
+    TemporaryFile output;
+    output.DoNotRemove();
+    DeployPatchGenerator generator(true);
+    generator.CreatePatch(apkPath.c_str(), metadata, output.fd);
+
+    // Expect a patch file that is smaller than 0.5K.
+    int64_t patchSize = adb_lseek(output.fd, 0L, SEEK_END);
+    EXPECT_LE(patchSize, 512);
+}
diff --git a/adb/fastdeploy/deploypatchgenerator/manifest.txt b/adb/fastdeploy/deploypatchgenerator/manifest.txt
deleted file mode 100644
index 5c00505..0000000
--- a/adb/fastdeploy/deploypatchgenerator/manifest.txt
+++ /dev/null
@@ -1 +0,0 @@
-Main-Class: com.android.fastdeploy.DeployPatchGenerator
diff --git a/adb/fastdeploy/deploypatchgenerator/patch_utils.cpp b/adb/fastdeploy/deploypatchgenerator/patch_utils.cpp
new file mode 100644
index 0000000..2b00c80
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/patch_utils.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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 "patch_utils.h"
+
+#include <stdio.h>
+
+#include "adb_io.h"
+#include "adb_utils.h"
+#include "android-base/endian.h"
+#include "sysdeps.h"
+
+#include "apk_archive.h"
+
+using namespace com::android;
+using namespace com::android::fastdeploy;
+using namespace android::base;
+
+static constexpr char kSignature[] = "FASTDEPLOY";
+
+APKMetaData PatchUtils::GetDeviceAPKMetaData(const APKDump& apk_dump) {
+    APKMetaData apkMetaData;
+    apkMetaData.set_absolute_path(apk_dump.absolute_path());
+
+    std::string md5Hash;
+    int64_t localFileHeaderOffset;
+    int64_t dataSize;
+
+    const auto& cd = apk_dump.cd();
+    auto cur = cd.data();
+    int64_t size = cd.size();
+    while (auto consumed = ApkArchive::ParseCentralDirectoryRecord(
+                   cur, size, &md5Hash, &localFileHeaderOffset, &dataSize)) {
+        cur += consumed;
+        size -= consumed;
+
+        auto apkEntry = apkMetaData.add_entries();
+        apkEntry->set_md5(md5Hash);
+        apkEntry->set_dataoffset(localFileHeaderOffset);
+        apkEntry->set_datasize(dataSize);
+    }
+    return apkMetaData;
+}
+
+APKMetaData PatchUtils::GetHostAPKMetaData(const char* apkPath) {
+    ApkArchive archive(apkPath);
+    auto dump = archive.ExtractMetadata();
+    if (dump.cd().empty()) {
+        fprintf(stderr, "adb: Could not extract Central Directory from %s\n", apkPath);
+        error_exit("Aborting");
+    }
+
+    auto apkMetaData = GetDeviceAPKMetaData(dump);
+
+    // Now let's set data sizes.
+    for (auto& apkEntry : *apkMetaData.mutable_entries()) {
+        auto dataSize =
+                archive.CalculateLocalFileEntrySize(apkEntry.dataoffset(), apkEntry.datasize());
+        if (dataSize == 0) {
+            error_exit("Aborting");
+        }
+        apkEntry.set_datasize(dataSize);
+    }
+
+    return apkMetaData;
+}
+
+void PatchUtils::WriteSignature(borrowed_fd output) {
+    WriteFdExactly(output, kSignature, sizeof(kSignature) - 1);
+}
+
+void PatchUtils::WriteLong(int64_t value, borrowed_fd output) {
+    int64_t littleEndian = htole64(value);
+    WriteFdExactly(output, &littleEndian, sizeof(littleEndian));
+}
+
+void PatchUtils::WriteString(const std::string& value, android::base::borrowed_fd output) {
+    WriteLong(value.size(), output);
+    WriteFdExactly(output, value);
+}
+
+void PatchUtils::Pipe(borrowed_fd input, borrowed_fd output, size_t amount) {
+    constexpr static size_t BUFFER_SIZE = 128 * 1024;
+    char buffer[BUFFER_SIZE];
+    size_t transferAmount = 0;
+    while (transferAmount != amount) {
+        auto chunkAmount = std::min(amount - transferAmount, BUFFER_SIZE);
+        auto readAmount = adb_read(input, buffer, chunkAmount);
+        if (readAmount < 0) {
+            fprintf(stderr, "adb: failed to read from input: %s\n", strerror(errno));
+            error_exit("Aborting");
+        }
+        WriteFdExactly(output, buffer, readAmount);
+        transferAmount += readAmount;
+    }
+}
diff --git a/adb/fastdeploy/deploypatchgenerator/patch_utils.h b/adb/fastdeploy/deploypatchgenerator/patch_utils.h
new file mode 100644
index 0000000..8dc9b9c
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/patch_utils.h
@@ -0,0 +1,57 @@
+/*
+ * 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 "adb_unique_fd.h"
+#include "fastdeploy/proto/ApkEntry.pb.h"
+
+/**
+ * Helper class that mirrors the PatchUtils from deploy agent.
+ */
+class PatchUtils {
+  public:
+    /**
+     * This function takes the dump of Central Directly and builds the APKMetaData required by the
+     * patching algorithm. The if this function has an error a string is printed to the terminal and
+     * exit(1) is called.
+     */
+    static com::android::fastdeploy::APKMetaData GetDeviceAPKMetaData(
+            const com::android::fastdeploy::APKDump& apk_dump);
+    /**
+     * This function takes a local APK file and builds the APKMetaData required by the patching
+     * algorithm. The if this function has an error a string is printed to the terminal and exit(1)
+     * is called.
+     */
+    static com::android::fastdeploy::APKMetaData GetHostAPKMetaData(const char* file);
+    /**
+     * Writes a fixed signature string to the header of the patch.
+     */
+    static void WriteSignature(android::base::borrowed_fd output);
+    /**
+     * Writes an int64 to the |output| reversing the bytes.
+     */
+    static void WriteLong(int64_t value, android::base::borrowed_fd output);
+    /**
+     * Writes string to the |output|.
+     */
+    static void WriteString(const std::string& value, android::base::borrowed_fd output);
+    /**
+     * Copy |amount| of data from |input| to |output|.
+     */
+    static void Pipe(android::base::borrowed_fd input, android::base::borrowed_fd output,
+                     size_t amount);
+};
diff --git a/adb/fastdeploy/deploypatchgenerator/patch_utils_test.cpp b/adb/fastdeploy/deploypatchgenerator/patch_utils_test.cpp
new file mode 100644
index 0000000..3ec5ab3
--- /dev/null
+++ b/adb/fastdeploy/deploypatchgenerator/patch_utils_test.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 "patch_utils.h"
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sstream>
+#include <string>
+
+#include <google/protobuf/util/message_differencer.h>
+
+#include "adb_io.h"
+#include "sysdeps.h"
+
+using namespace com::android::fastdeploy;
+using google::protobuf::util::MessageDifferencer;
+
+static std::string GetTestFile(const std::string& name) {
+    return "fastdeploy/testdata/" + name;
+}
+
+bool FileMatchesContent(android::base::borrowed_fd input, const char* contents,
+                        ssize_t contentsSize) {
+    adb_lseek(input, 0, SEEK_SET);
+    // Use a temp buffer larger than any test contents.
+    constexpr int BUFFER_SIZE = 2048;
+    char buffer[BUFFER_SIZE];
+    bool result = true;
+    // Validate size of files is equal.
+    ssize_t readAmount = adb_read(input, buffer, BUFFER_SIZE);
+    EXPECT_EQ(readAmount, contentsSize);
+    result = memcmp(buffer, contents, readAmount) == 0;
+    for (int i = 0; i < readAmount; i++) {
+        printf("%x", buffer[i]);
+    }
+    printf(" == ");
+    for (int i = 0; i < contentsSize; i++) {
+        printf("%x", contents[i]);
+    }
+    printf("\n");
+
+    return result;
+}
+
+TEST(PatchUtilsTest, SwapLongWrites) {
+    TemporaryFile output;
+    PatchUtils::WriteLong(0x0011223344556677, output.fd);
+    adb_lseek(output.fd, 0, SEEK_SET);
+    const char expected[] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00};
+    EXPECT_TRUE(FileMatchesContent(output.fd, expected, 8));
+}
+
+TEST(PatchUtilsTest, PipeWritesAmountToOutput) {
+    std::string expected("Some Data");
+    TemporaryFile input;
+    TemporaryFile output;
+    // Populate input file.
+    WriteFdExactly(input.fd, expected);
+    adb_lseek(input.fd, 0, SEEK_SET);
+    // Open input file for read, and output file for write.
+    PatchUtils::Pipe(input.fd, output.fd, expected.size());
+    // Validate pipe worked
+    EXPECT_TRUE(FileMatchesContent(output.fd, expected.c_str(), expected.size()));
+}
+
+TEST(PatchUtilsTest, SignatureConstMatches) {
+    std::string apkFile = GetTestFile("rotating_cube-release.apk");
+    TemporaryFile output;
+    PatchUtils::WriteSignature(output.fd);
+    std::string contents("FASTDEPLOY");
+    EXPECT_TRUE(FileMatchesContent(output.fd, contents.c_str(), contents.size()));
+}
+
+TEST(PatchUtilsTest, GatherMetadata) {
+    std::string apkFile = GetTestFile("rotating_cube-release.apk");
+    APKMetaData actual = PatchUtils::GetHostAPKMetaData(apkFile.c_str());
+
+    std::string expectedMetadata;
+    android::base::ReadFileToString(GetTestFile("rotating_cube-metadata-release.data"),
+                                    &expectedMetadata);
+    APKMetaData expected;
+    EXPECT_TRUE(expected.ParseFromString(expectedMetadata));
+
+    // Test paths might vary.
+    expected.set_absolute_path(actual.absolute_path());
+
+    std::string actualMetadata;
+    actual.SerializeToString(&actualMetadata);
+
+    expected.SerializeToString(&expectedMetadata);
+
+    EXPECT_EQ(expectedMetadata, actualMetadata);
+}
+
+static inline void sanitize(APKMetaData& metadata) {
+    metadata.clear_absolute_path();
+    for (auto&& entry : *metadata.mutable_entries()) {
+        entry.clear_datasize();
+    }
+}
+
+TEST(PatchUtilsTest, GatherDumpMetadata) {
+    APKMetaData hostMetadata;
+    APKMetaData deviceMetadata;
+
+    hostMetadata = PatchUtils::GetHostAPKMetaData(GetTestFile("sample.apk").c_str());
+
+    {
+        std::string cd;
+        android::base::ReadFileToString(GetTestFile("sample.cd"), &cd);
+
+        APKDump dump;
+        dump.set_cd(std::move(cd));
+
+        deviceMetadata = PatchUtils::GetDeviceAPKMetaData(dump);
+    }
+
+    sanitize(hostMetadata);
+    sanitize(deviceMetadata);
+
+    std::string expectedMetadata;
+    hostMetadata.SerializeToString(&expectedMetadata);
+
+    std::string actualMetadata;
+    deviceMetadata.SerializeToString(&actualMetadata);
+
+    EXPECT_EQ(expectedMetadata, actualMetadata);
+}
diff --git a/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java b/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java
deleted file mode 100644
index 24b2eab..0000000
--- a/adb/fastdeploy/deploypatchgenerator/src/com/android/fastdeploy/DeployPatchGenerator.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.fastdeploy;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.StringBuilder;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.ArrayList;
-
-import java.nio.charset.StandardCharsets;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.AbstractMap.SimpleEntry;
-
-import com.android.fastdeploy.APKMetaData;
-import com.android.fastdeploy.APKEntry;
-
-public final class DeployPatchGenerator {
-    private static final int BUFFER_SIZE = 128 * 1024;
-
-    public static void main(String[] args) {
-        try {
-            if (args.length < 2) {
-                showUsage(0);
-            }
-
-            boolean verbose = false;
-            if (args.length > 2) {
-                String verboseFlag = args[2];
-                if (verboseFlag.compareTo("--verbose") == 0) {
-                    verbose = true;
-                }
-            }
-
-            StringBuilder sb = null;
-            String apkPath = args[0];
-            String deviceMetadataPath = args[1];
-            File hostFile = new File(apkPath);
-
-            List<APKEntry> deviceZipEntries = getMetadataFromFile(deviceMetadataPath);
-            System.err.println("Device Entries (" + deviceZipEntries.size() + ")");
-            if (verbose) {
-                sb = new StringBuilder();
-                for (APKEntry entry : deviceZipEntries) {
-                    APKEntryToString(entry, sb);
-                }
-                System.err.println(sb.toString());
-            }
-
-            List<APKEntry> hostFileEntries = PatchUtils.getAPKMetaData(hostFile).getEntriesList();
-            System.err.println("Host Entries (" + hostFileEntries.size() + ")");
-            if (verbose) {
-                sb = new StringBuilder();
-                for (APKEntry entry : hostFileEntries) {
-                    APKEntryToString(entry, sb);
-                }
-                System.err.println(sb.toString());
-            }
-
-            List<SimpleEntry<APKEntry, APKEntry>> identicalContentsEntrySet =
-                getIdenticalContents(deviceZipEntries, hostFileEntries);
-            reportIdenticalContents(identicalContentsEntrySet, hostFile);
-
-            if (verbose) {
-                sb = new StringBuilder();
-                for (SimpleEntry<APKEntry, APKEntry> identicalEntry : identicalContentsEntrySet) {
-                    APKEntry entry = identicalEntry.getValue();
-                    APKEntryToString(entry, sb);
-                }
-                System.err.println("Identical Entries (" + identicalContentsEntrySet.size() + ")");
-                System.err.println(sb.toString());
-            }
-
-            createPatch(identicalContentsEntrySet, hostFile, System.out);
-        } catch (Exception e) {
-            System.err.println("Error: " + e);
-            e.printStackTrace();
-            System.exit(2);
-        }
-        System.exit(0);
-    }
-
-    private static void showUsage(int exitCode) {
-        System.err.println("usage: deploypatchgenerator <apkpath> <deviceapkmetadata> [--verbose]");
-        System.err.println("");
-        System.exit(exitCode);
-    }
-
-    private static void APKEntryToString(APKEntry entry, StringBuilder outputString) {
-        outputString.append(String.format("Filename: %s\n", entry.getFileName()));
-        outputString.append(String.format("CRC32: 0x%08X\n", entry.getCrc32()));
-        outputString.append(String.format("Data Offset: %d\n", entry.getDataOffset()));
-        outputString.append(String.format("Compressed Size: %d\n", entry.getCompressedSize()));
-        outputString.append(String.format("Uncompressed Size: %d\n", entry.getUncompressedSize()));
-    }
-
-    private static List<APKEntry> getMetadataFromFile(String deviceMetadataPath) throws IOException {
-        InputStream is = new FileInputStream(new File(deviceMetadataPath));
-        APKMetaData apkMetaData = APKMetaData.parseDelimitedFrom(is);
-        return apkMetaData.getEntriesList();
-    }
-
-    private static List<SimpleEntry<APKEntry, APKEntry>> getIdenticalContents(
-        List<APKEntry> deviceZipEntries, List<APKEntry> hostZipEntries) throws IOException {
-        List<SimpleEntry<APKEntry, APKEntry>> identicalContents =
-            new ArrayList<SimpleEntry<APKEntry, APKEntry>>();
-
-        for (APKEntry deviceZipEntry : deviceZipEntries) {
-            for (APKEntry hostZipEntry : hostZipEntries) {
-                if (deviceZipEntry.getCrc32() == hostZipEntry.getCrc32() &&
-                    deviceZipEntry.getFileName().equals(hostZipEntry.getFileName())) {
-                    identicalContents.add(new SimpleEntry(deviceZipEntry, hostZipEntry));
-                }
-            }
-        }
-
-        Collections.sort(identicalContents, new Comparator<SimpleEntry<APKEntry, APKEntry>>() {
-            @Override
-            public int compare(
-                SimpleEntry<APKEntry, APKEntry> p1, SimpleEntry<APKEntry, APKEntry> p2) {
-                return Long.compare(p1.getValue().getDataOffset(), p2.getValue().getDataOffset());
-            }
-        });
-
-        return identicalContents;
-    }
-
-    private static void reportIdenticalContents(
-        List<SimpleEntry<APKEntry, APKEntry>> identicalContentsEntrySet, File hostFile)
-        throws IOException {
-        long totalEqualBytes = 0;
-        int totalEqualFiles = 0;
-        for (SimpleEntry<APKEntry, APKEntry> entries : identicalContentsEntrySet) {
-            APKEntry hostAPKEntry = entries.getValue();
-            totalEqualBytes += hostAPKEntry.getCompressedSize();
-            totalEqualFiles++;
-        }
-
-        float savingPercent = (float) (totalEqualBytes * 100) / hostFile.length();
-
-        System.err.println("Detected " + totalEqualFiles + " equal APK entries");
-        System.err.println(totalEqualBytes + " bytes are equal out of " + hostFile.length() + " ("
-            + savingPercent + "%)");
-    }
-
-    static void createPatch(List<SimpleEntry<APKEntry, APKEntry>> zipEntrySimpleEntrys,
-        File hostFile, OutputStream patchStream) throws IOException, PatchFormatException {
-        FileInputStream hostFileInputStream = new FileInputStream(hostFile);
-
-        patchStream.write(PatchUtils.SIGNATURE.getBytes(StandardCharsets.US_ASCII));
-        PatchUtils.writeFormattedLong(hostFile.length(), patchStream);
-
-        byte[] buffer = new byte[BUFFER_SIZE];
-        long totalBytesWritten = 0;
-        Iterator<SimpleEntry<APKEntry, APKEntry>> entrySimpleEntryIterator =
-            zipEntrySimpleEntrys.iterator();
-        while (entrySimpleEntryIterator.hasNext()) {
-            SimpleEntry<APKEntry, APKEntry> entrySimpleEntry = entrySimpleEntryIterator.next();
-            APKEntry deviceAPKEntry = entrySimpleEntry.getKey();
-            APKEntry hostAPKEntry = entrySimpleEntry.getValue();
-
-            long newDataLen = hostAPKEntry.getDataOffset() - totalBytesWritten;
-            long oldDataOffset = deviceAPKEntry.getDataOffset();
-            long oldDataLen = deviceAPKEntry.getCompressedSize();
-
-            PatchUtils.writeFormattedLong(newDataLen, patchStream);
-            PatchUtils.pipe(hostFileInputStream, patchStream, buffer, newDataLen);
-            PatchUtils.writeFormattedLong(oldDataOffset, patchStream);
-            PatchUtils.writeFormattedLong(oldDataLen, patchStream);
-
-            long skip = hostFileInputStream.skip(oldDataLen);
-            if (skip != oldDataLen) {
-                throw new PatchFormatException("skip error: attempted to skip " + oldDataLen
-                    + " bytes but return code was " + skip);
-            }
-            totalBytesWritten += oldDataLen + newDataLen;
-        }
-        long remainderLen = hostFile.length() - totalBytesWritten;
-        PatchUtils.writeFormattedLong(remainderLen, patchStream);
-        PatchUtils.pipe(hostFileInputStream, patchStream, buffer, remainderLen);
-        PatchUtils.writeFormattedLong(0, patchStream);
-        PatchUtils.writeFormattedLong(0, patchStream);
-        patchStream.flush();
-    }
-}
diff --git a/adb/fastdeploy/proto/ApkEntry.proto b/adb/fastdeploy/proto/ApkEntry.proto
index 9460d15..d84c5a5 100644
--- a/adb/fastdeploy/proto/ApkEntry.proto
+++ b/adb/fastdeploy/proto/ApkEntry.proto
@@ -1,18 +1,26 @@
-syntax = "proto2";
+syntax = "proto3";
 
 package com.android.fastdeploy;
 
 option java_package = "com.android.fastdeploy";
+option java_outer_classname = "ApkEntryProto";
 option java_multiple_files = true;
+option optimize_for = LITE_RUNTIME;
+
+message APKDump {
+    string name = 1;
+    bytes cd = 2;
+    bytes signature = 3;
+    string absolute_path = 4;
+}
 
 message APKEntry {
-    required int64 crc32 = 1;
-    required string fileName = 2;
-    required int64 dataOffset = 3;
-    required int64 compressedSize = 4;
-    required int64 uncompressedSize = 5;
+    bytes md5 = 1;
+    int64 dataOffset = 2;
+    int64 dataSize = 3;
 }
 
 message APKMetaData {
-    repeated APKEntry entries = 1;
+    string absolute_path = 1;
+    repeated APKEntry entries = 2;
 }
diff --git a/adb/fastdeploy/testdata/helloworld5.apk b/adb/fastdeploy/testdata/helloworld5.apk
new file mode 100644
index 0000000..4a1539e
--- /dev/null
+++ b/adb/fastdeploy/testdata/helloworld5.apk
Binary files differ
diff --git a/adb/fastdeploy/testdata/helloworld7.apk b/adb/fastdeploy/testdata/helloworld7.apk
new file mode 100644
index 0000000..82c46df
--- /dev/null
+++ b/adb/fastdeploy/testdata/helloworld7.apk
Binary files differ
diff --git a/adb/fastdeploy/testdata/rotating_cube-metadata-release.data b/adb/fastdeploy/testdata/rotating_cube-metadata-release.data
new file mode 100644
index 0000000..52352ff
--- /dev/null
+++ b/adb/fastdeploy/testdata/rotating_cube-metadata-release.data
Binary files differ
diff --git a/adb/fastdeploy/testdata/rotating_cube-release.apk b/adb/fastdeploy/testdata/rotating_cube-release.apk
new file mode 100644
index 0000000..d47e0ea
--- /dev/null
+++ b/adb/fastdeploy/testdata/rotating_cube-release.apk
Binary files differ
diff --git a/adb/fastdeploy/testdata/sample.apk b/adb/fastdeploy/testdata/sample.apk
new file mode 100644
index 0000000..c316205
--- /dev/null
+++ b/adb/fastdeploy/testdata/sample.apk
Binary files differ
diff --git a/adb/fastdeploy/testdata/sample.cd b/adb/fastdeploy/testdata/sample.cd
new file mode 100644
index 0000000..5e5b4d4
--- /dev/null
+++ b/adb/fastdeploy/testdata/sample.cd
Binary files differ
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
deleted file mode 100644
index 32f9086..0000000
--- a/adb/fdevent.cpp
+++ /dev/null
@@ -1,553 +0,0 @@
-/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
-**
-** Copyright 2006, Brian Swetland <swetland@frotz.net>
-**
-** 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 TRACE_TAG FDEVENT
-
-#include "sysdeps.h"
-#include "fdevent.h"
-
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <deque>
-#include <functional>
-#include <list>
-#include <mutex>
-#include <optional>
-#include <unordered_map>
-#include <utility>
-#include <variant>
-#include <vector>
-
-#include <android-base/chrono_utils.h>
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/thread_annotations.h>
-#include <android-base/threads.h>
-
-#include "adb_io.h"
-#include "adb_trace.h"
-#include "adb_unique_fd.h"
-#include "adb_utils.h"
-#include "sysdeps/chrono.h"
-
-#define FDE_EVENTMASK  0x00ff
-#define FDE_STATEMASK  0xff00
-
-#define FDE_ACTIVE     0x0100
-#define FDE_PENDING    0x0200
-#define FDE_CREATED    0x0400
-
-struct PollNode {
-  fdevent* fde;
-  adb_pollfd pollfd;
-
-  explicit PollNode(fdevent* fde) : fde(fde) {
-      memset(&pollfd, 0, sizeof(pollfd));
-      pollfd.fd = fde->fd.get();
-
-#if defined(__linux__)
-      // Always enable POLLRDHUP, so the host server can take action when some clients disconnect.
-      // Then we can avoid leaving many sockets in CLOSE_WAIT state. See http://b/23314034.
-      pollfd.events = POLLRDHUP;
-#endif
-  }
-};
-
-// All operations to fdevent should happen only in the main thread.
-// That's why we don't need a lock for fdevent.
-static auto& g_poll_node_map = *new std::unordered_map<int, PollNode>();
-static auto& g_pending_list = *new std::list<fdevent*>();
-static std::atomic<bool> terminate_loop(false);
-static bool main_thread_valid;
-static uint64_t main_thread_id;
-
-static uint64_t fdevent_id;
-
-static bool run_needs_flush = false;
-static auto& run_queue_notify_fd = *new unique_fd();
-static auto& run_queue_mutex = *new std::mutex();
-static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::deque<std::function<void()>>();
-
-void check_main_thread() {
-    if (main_thread_valid) {
-        CHECK_EQ(main_thread_id, android::base::GetThreadId());
-    }
-}
-
-void set_main_thread() {
-    main_thread_valid = true;
-    main_thread_id = android::base::GetThreadId();
-}
-
-static std::string dump_fde(const fdevent* fde) {
-    std::string state;
-    if (fde->state & FDE_ACTIVE) {
-        state += "A";
-    }
-    if (fde->state & FDE_PENDING) {
-        state += "P";
-    }
-    if (fde->state & FDE_CREATED) {
-        state += "C";
-    }
-    if (fde->state & FDE_READ) {
-        state += "R";
-    }
-    if (fde->state & FDE_WRITE) {
-        state += "W";
-    }
-    if (fde->state & FDE_ERROR) {
-        state += "E";
-    }
-    return android::base::StringPrintf("(fdevent %" PRIu64 ": fd %d %s)", fde->id, fde->fd.get(),
-                                       state.c_str());
-}
-
-template <typename F>
-static fdevent* fdevent_create_impl(int fd, F func, void* arg) {
-    check_main_thread();
-    CHECK_GE(fd, 0);
-
-    fdevent* fde = new fdevent();
-    fde->id = fdevent_id++;
-    fde->state = FDE_ACTIVE;
-    fde->fd.reset(fd);
-    fde->func = func;
-    fde->arg = arg;
-    if (!set_file_block_mode(fd, false)) {
-        // Here is not proper to handle the error. If it fails here, some error is
-        // likely to be detected by poll(), then we can let the callback function
-        // to handle it.
-        LOG(ERROR) << "failed to set non-blocking mode for fd " << fd;
-    }
-    auto pair = g_poll_node_map.emplace(fde->fd.get(), PollNode(fde));
-    CHECK(pair.second) << "install existing fd " << fd;
-
-    fde->state |= FDE_CREATED;
-    return fde;
-}
-
-fdevent* fdevent_create(int fd, fd_func func, void* arg) {
-    return fdevent_create_impl(fd, func, arg);
-}
-
-fdevent* fdevent_create(int fd, fd_func2 func, void* arg) {
-    return fdevent_create_impl(fd, func, arg);
-}
-
-unique_fd fdevent_release(fdevent* fde) {
-    check_main_thread();
-    if (!fde) {
-        return {};
-    }
-
-    if (!(fde->state & FDE_CREATED)) {
-        LOG(FATAL) << "destroying fde not created by fdevent_create(): " << dump_fde(fde);
-    }
-
-    unique_fd result = std::move(fde->fd);
-    if (fde->state & FDE_ACTIVE) {
-        g_poll_node_map.erase(result.get());
-
-        if (fde->state & FDE_PENDING) {
-            g_pending_list.remove(fde);
-        }
-        fde->state = 0;
-        fde->events = 0;
-    }
-
-    delete fde;
-    return result;
-}
-
-void fdevent_destroy(fdevent* fde) {
-    // Release, and then let unique_fd's destructor cleanup.
-    fdevent_release(fde);
-}
-
-static void fdevent_update(fdevent* fde, unsigned events) {
-    auto it = g_poll_node_map.find(fde->fd.get());
-    CHECK(it != g_poll_node_map.end());
-    PollNode& node = it->second;
-    if (events & FDE_READ) {
-        node.pollfd.events |= POLLIN;
-    } else {
-        node.pollfd.events &= ~POLLIN;
-    }
-
-    if (events & FDE_WRITE) {
-        node.pollfd.events |= POLLOUT;
-    } else {
-        node.pollfd.events &= ~POLLOUT;
-    }
-    fde->state = (fde->state & FDE_STATEMASK) | events;
-}
-
-void fdevent_set(fdevent* fde, unsigned events) {
-    check_main_thread();
-    events &= FDE_EVENTMASK;
-    if ((fde->state & FDE_EVENTMASK) == events) {
-        return;
-    }
-    CHECK(fde->state & FDE_ACTIVE);
-    fdevent_update(fde, events);
-    D("fdevent_set: %s, events = %u", dump_fde(fde).c_str(), events);
-
-    if (fde->state & FDE_PENDING) {
-        // If we are pending, make sure we don't signal an event that is no longer wanted.
-        fde->events &= events;
-        if (fde->events == 0) {
-            g_pending_list.remove(fde);
-            fde->state &= ~FDE_PENDING;
-        }
-    }
-}
-
-void fdevent_add(fdevent* fde, unsigned events) {
-    check_main_thread();
-    CHECK(!(events & FDE_TIMEOUT));
-    fdevent_set(fde, (fde->state & FDE_EVENTMASK) | events);
-}
-
-void fdevent_del(fdevent* fde, unsigned events) {
-    check_main_thread();
-    CHECK(!(events & FDE_TIMEOUT));
-    fdevent_set(fde, (fde->state & FDE_EVENTMASK) & ~events);
-}
-
-void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
-    check_main_thread();
-    fde->timeout = timeout;
-    fde->last_active = std::chrono::steady_clock::now();
-}
-
-static std::string dump_pollfds(const std::vector<adb_pollfd>& pollfds) {
-    std::string result;
-    for (const auto& pollfd : pollfds) {
-        std::string op;
-        if (pollfd.events & POLLIN) {
-            op += "R";
-        }
-        if (pollfd.events & POLLOUT) {
-            op += "W";
-        }
-        android::base::StringAppendF(&result, " %d(%s)", pollfd.fd, op.c_str());
-    }
-    return result;
-}
-
-static std::optional<std::chrono::milliseconds> calculate_timeout() {
-    std::optional<std::chrono::milliseconds> result = std::nullopt;
-    auto now = std::chrono::steady_clock::now();
-    check_main_thread();
-
-    for (const auto& [fd, pollnode] : g_poll_node_map) {
-        UNUSED(fd);
-        auto timeout_opt = pollnode.fde->timeout;
-        if (timeout_opt) {
-            auto deadline = pollnode.fde->last_active + *timeout_opt;
-            auto time_left = std::chrono::duration_cast<std::chrono::milliseconds>(deadline - now);
-            if (time_left < std::chrono::milliseconds::zero()) {
-                time_left = std::chrono::milliseconds::zero();
-            }
-
-            if (!result) {
-                result = time_left;
-            } else {
-                result = std::min(*result, time_left);
-            }
-        }
-    }
-
-    return result;
-}
-
-static void fdevent_process() {
-    std::vector<adb_pollfd> pollfds;
-    for (const auto& pair : g_poll_node_map) {
-        pollfds.push_back(pair.second.pollfd);
-    }
-    CHECK_GT(pollfds.size(), 0u);
-    D("poll(), pollfds = %s", dump_pollfds(pollfds).c_str());
-
-    auto timeout = calculate_timeout();
-    int timeout_ms;
-    if (!timeout) {
-        timeout_ms = -1;
-    } else {
-        timeout_ms = timeout->count();
-    }
-
-    int ret = adb_poll(&pollfds[0], pollfds.size(), timeout_ms);
-    if (ret == -1) {
-        PLOG(ERROR) << "poll(), ret = " << ret;
-        return;
-    }
-
-    auto post_poll = std::chrono::steady_clock::now();
-
-    for (const auto& pollfd : pollfds) {
-        if (pollfd.revents != 0) {
-            D("for fd %d, revents = %x", pollfd.fd, pollfd.revents);
-        }
-        unsigned events = 0;
-        if (pollfd.revents & POLLIN) {
-            events |= FDE_READ;
-        }
-        if (pollfd.revents & POLLOUT) {
-            events |= FDE_WRITE;
-        }
-        if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
-            // We fake a read, as the rest of the code assumes that errors will
-            // be detected at that point.
-            events |= FDE_READ | FDE_ERROR;
-        }
-#if defined(__linux__)
-        if (pollfd.revents & POLLRDHUP) {
-            events |= FDE_READ | FDE_ERROR;
-        }
-#endif
-        auto it = g_poll_node_map.find(pollfd.fd);
-        CHECK(it != g_poll_node_map.end());
-        fdevent* fde = it->second.fde;
-
-        if (events == 0) {
-            // Check for timeout.
-            if (fde->timeout) {
-                auto deadline = fde->last_active + *fde->timeout;
-                if (deadline < post_poll) {
-                    events |= FDE_TIMEOUT;
-                }
-            }
-        }
-
-        if (events != 0) {
-            CHECK_EQ(fde->fd.get(), pollfd.fd);
-            fde->events |= events;
-            fde->last_active = post_poll;
-            D("%s got events %x", dump_fde(fde).c_str(), events);
-            fde->state |= FDE_PENDING;
-            g_pending_list.push_back(fde);
-        }
-    }
-}
-
-template <class T>
-struct always_false : std::false_type {};
-
-static void fdevent_call_fdfunc(fdevent* fde) {
-    unsigned events = fde->events;
-    fde->events = 0;
-    CHECK(fde->state & FDE_PENDING);
-    fde->state &= (~FDE_PENDING);
-    D("fdevent_call_fdfunc %s", dump_fde(fde).c_str());
-    std::visit(
-            [&](auto&& f) {
-                using F = std::decay_t<decltype(f)>;
-                if constexpr (std::is_same_v<fd_func, F>) {
-                    f(fde->fd.get(), events, fde->arg);
-                } else if constexpr (std::is_same_v<fd_func2, F>) {
-                    f(fde, events, fde->arg);
-                } else {
-                    static_assert(always_false<F>::value, "non-exhaustive visitor");
-                }
-            },
-            fde->func);
-}
-
-static void fdevent_run_flush() EXCLUDES(run_queue_mutex) {
-    // We need to be careful around reentrancy here, since a function we call can queue up another
-    // function.
-    while (true) {
-        std::function<void()> fn;
-        {
-            std::lock_guard<std::mutex> lock(run_queue_mutex);
-            if (run_queue.empty()) {
-                break;
-            }
-            fn = run_queue.front();
-            run_queue.pop_front();
-        }
-        fn();
-    }
-}
-
-static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) {
-    CHECK_GE(fd, 0);
-    CHECK(ev & FDE_READ);
-
-    char buf[1024];
-
-    // Empty the fd.
-    if (adb_read(fd, buf, sizeof(buf)) == -1) {
-        PLOG(FATAL) << "failed to empty run queue notify fd";
-    }
-
-    // Mark that we need to flush, and then run it at the end of fdevent_loop.
-    run_needs_flush = true;
-}
-
-static void fdevent_run_setup() {
-    {
-        std::lock_guard<std::mutex> lock(run_queue_mutex);
-        CHECK(run_queue_notify_fd.get() == -1);
-        int s[2];
-        if (adb_socketpair(s) != 0) {
-            PLOG(FATAL) << "failed to create run queue notify socketpair";
-        }
-
-        if (!set_file_block_mode(s[0], false) || !set_file_block_mode(s[1], false)) {
-            PLOG(FATAL) << "failed to make run queue notify socket nonblocking";
-        }
-
-        run_queue_notify_fd.reset(s[0]);
-        fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr);
-        CHECK(fde != nullptr);
-        fdevent_add(fde, FDE_READ);
-    }
-
-    fdevent_run_flush();
-}
-
-void fdevent_run_on_main_thread(std::function<void()> fn) {
-    std::lock_guard<std::mutex> lock(run_queue_mutex);
-    run_queue.push_back(std::move(fn));
-
-    // run_queue_notify_fd could still be -1 if we're called before fdevent has finished setting up.
-    // In that case, rely on the setup code to flush the queue without a notification being needed.
-    if (run_queue_notify_fd != -1) {
-        int rc = adb_write(run_queue_notify_fd.get(), "", 1);
-
-        // It's possible that we get EAGAIN here, if lots of notifications came in while handling.
-        if (rc == 0) {
-            PLOG(FATAL) << "run queue notify fd was closed?";
-        } else if (rc == -1 && errno != EAGAIN) {
-            PLOG(FATAL) << "failed to write to run queue notify fd";
-        }
-    }
-}
-
-static void fdevent_check_spin(uint64_t cycle) {
-    // Check to see if we're spinning because we forgot about an fdevent
-    // by keeping track of how long fdevents have been continuously pending.
-    struct SpinCheck {
-        fdevent* fde;
-        android::base::boot_clock::time_point timestamp;
-        uint64_t cycle;
-    };
-    static auto& g_continuously_pending = *new std::unordered_map<uint64_t, SpinCheck>();
-    static auto last_cycle = android::base::boot_clock::now();
-
-    auto now = android::base::boot_clock::now();
-    if (now - last_cycle > 10ms) {
-        // We're not spinning.
-        g_continuously_pending.clear();
-        last_cycle = now;
-        return;
-    }
-    last_cycle = now;
-
-    for (auto* fde : g_pending_list) {
-        auto it = g_continuously_pending.find(fde->id);
-        if (it == g_continuously_pending.end()) {
-            g_continuously_pending[fde->id] =
-                    SpinCheck{.fde = fde, .timestamp = now, .cycle = cycle};
-        } else {
-            it->second.cycle = cycle;
-        }
-    }
-
-    for (auto it = g_continuously_pending.begin(); it != g_continuously_pending.end();) {
-        if (it->second.cycle != cycle) {
-            it = g_continuously_pending.erase(it);
-        } else {
-            // Use an absurdly long window, since all we really care about is
-            // getting a bugreport eventually.
-            if (now - it->second.timestamp > 300s) {
-                LOG(FATAL_WITHOUT_ABORT)
-                        << "detected spin in fdevent: " << dump_fde(it->second.fde);
-#if defined(__linux__)
-                int fd = it->second.fde->fd.get();
-                std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
-                std::string path;
-                if (!android::base::Readlink(fd_path, &path)) {
-                    PLOG(FATAL_WITHOUT_ABORT) << "readlink of fd " << fd << " failed";
-                }
-                LOG(FATAL_WITHOUT_ABORT) << "fd " << fd << " = " << path;
-#endif
-                abort();
-            }
-            ++it;
-        }
-    }
-}
-
-void fdevent_loop() {
-    set_main_thread();
-    fdevent_run_setup();
-
-    uint64_t cycle = 0;
-    while (true) {
-        if (terminate_loop) {
-            return;
-        }
-
-        D("--- --- waiting for events");
-
-        fdevent_process();
-
-        fdevent_check_spin(cycle++);
-
-        while (!g_pending_list.empty()) {
-            fdevent* fde = g_pending_list.front();
-            g_pending_list.pop_front();
-            fdevent_call_fdfunc(fde);
-        }
-
-        if (run_needs_flush) {
-            fdevent_run_flush();
-            run_needs_flush = false;
-        }
-    }
-}
-
-void fdevent_terminate_loop() {
-    terminate_loop = true;
-}
-
-size_t fdevent_installed_count() {
-    return g_poll_node_map.size();
-}
-
-void fdevent_reset() {
-    g_poll_node_map.clear();
-    g_pending_list.clear();
-
-    std::lock_guard<std::mutex> lock(run_queue_mutex);
-    run_queue_notify_fd.reset();
-    run_queue.clear();
-
-    main_thread_valid = false;
-    terminate_loop = false;
-}
diff --git a/adb/fdevent.h b/adb/fdevent.h
deleted file mode 100644
index 42dbb9e..0000000
--- a/adb/fdevent.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2006 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 __FDEVENT_H
-#define __FDEVENT_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <chrono>
-#include <functional>
-#include <optional>
-#include <variant>
-
-#include "adb_unique_fd.h"
-
-// Events that may be observed
-#define FDE_READ 0x0001
-#define FDE_WRITE 0x0002
-#define FDE_ERROR 0x0004
-#define FDE_TIMEOUT 0x0008
-
-typedef void (*fd_func)(int fd, unsigned events, void *userdata);
-typedef void (*fd_func2)(struct fdevent* fde, unsigned events, void* userdata);
-
-struct fdevent {
-    uint64_t id;
-
-    unique_fd fd;
-    int force_eof = 0;
-
-    uint16_t state = 0;
-    uint16_t events = 0;
-    std::optional<std::chrono::milliseconds> timeout;
-    std::chrono::steady_clock::time_point last_active;
-
-    std::variant<fd_func, fd_func2> func;
-    void* arg = nullptr;
-};
-
-// Allocate and initialize a new fdevent object
-// TODO: Switch these to unique_fd.
-fdevent *fdevent_create(int fd, fd_func func, void *arg);
-fdevent* fdevent_create(int fd, fd_func2 func, void* arg);
-
-// Deallocate an fdevent object that was created by fdevent_create.
-void fdevent_destroy(fdevent *fde);
-
-// fdevent_destroy, except releasing the file descriptor previously owned by the fdevent.
-unique_fd fdevent_release(fdevent* fde);
-
-// Change which events should cause notifications
-void fdevent_set(fdevent *fde, unsigned events);
-void fdevent_add(fdevent *fde, unsigned events);
-void fdevent_del(fdevent *fde, unsigned events);
-
-// Set a timeout on an fdevent.
-// If no events are triggered by the timeout, an FDE_TIMEOUT will be generated.
-// Note timeouts are not defused automatically; if a timeout is set on an fdevent, it will
-// trigger repeatedly every |timeout| ms.
-void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout);
-
-// Loop forever, handling events.
-void fdevent_loop();
-
-void check_main_thread();
-
-// Queue an operation to run on the main thread.
-void fdevent_run_on_main_thread(std::function<void()> fn);
-
-// The following functions are used only for tests.
-void fdevent_terminate_loop();
-size_t fdevent_installed_count();
-void fdevent_reset();
-void set_main_thread();
-
-#endif
diff --git a/adb/fdevent/fdevent.cpp b/adb/fdevent/fdevent.cpp
new file mode 100644
index 0000000..562f587
--- /dev/null
+++ b/adb/fdevent/fdevent.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2006, Brian Swetland <swetland@frotz.net>
+ *
+ * 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 TRACE_TAG FDEVENT
+
+#include "sysdeps.h"
+
+#include <inttypes.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/threads.h>
+
+#include "adb_utils.h"
+#include "fdevent.h"
+#include "fdevent_epoll.h"
+#include "fdevent_poll.h"
+
+using namespace std::chrono_literals;
+using std::chrono::duration_cast;
+
+void invoke_fde(struct fdevent* fde, unsigned events) {
+    if (auto f = std::get_if<fd_func>(&fde->func)) {
+        (*f)(fde->fd.get(), events, fde->arg);
+    } else if (auto f = std::get_if<fd_func2>(&fde->func)) {
+        (*f)(fde, events, fde->arg);
+    } else {
+        __builtin_unreachable();
+    }
+}
+
+std::string dump_fde(const fdevent* fde) {
+    std::string state;
+    if (fde->state & FDE_READ) {
+        state += "R";
+    }
+    if (fde->state & FDE_WRITE) {
+        state += "W";
+    }
+    if (fde->state & FDE_ERROR) {
+        state += "E";
+    }
+    return android::base::StringPrintf("(fdevent %" PRIu64 ": fd %d %s)", fde->id, fde->fd.get(),
+                                       state.c_str());
+}
+
+fdevent* fdevent_context::Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg) {
+    CheckMainThread();
+    CHECK_GE(fd.get(), 0);
+
+    int fd_num = fd.get();
+
+    fdevent* fde = new fdevent();
+    fde->id = fdevent_id_++;
+    fde->state = 0;
+    fde->fd = std::move(fd);
+    fde->func = func;
+    fde->arg = arg;
+    if (!set_file_block_mode(fde->fd, false)) {
+        // Here is not proper to handle the error. If it fails here, some error is
+        // likely to be detected by poll(), then we can let the callback function
+        // to handle it.
+        LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get();
+    }
+
+    auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fde);
+    CHECK(inserted);
+    UNUSED(it);
+
+    this->Register(fde);
+    return fde;
+}
+
+unique_fd fdevent_context::Destroy(fdevent* fde) {
+    CheckMainThread();
+    if (!fde) {
+        return {};
+    }
+
+    this->Unregister(fde);
+
+    auto erased = this->installed_fdevents_.erase(fde->fd.get());
+    CHECK_EQ(1UL, erased);
+
+    unique_fd result = std::move(fde->fd);
+    delete fde;
+    return result;
+}
+
+void fdevent_context::Add(fdevent* fde, unsigned events) {
+    CHECK(!(events & FDE_TIMEOUT));
+    Set(fde, fde->state | events);
+}
+
+void fdevent_context::Del(fdevent* fde, unsigned events) {
+    CHECK(!(events & FDE_TIMEOUT));
+    Set(fde, fde->state & ~events);
+}
+
+void fdevent_context::SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
+    CheckMainThread();
+    fde->timeout = timeout;
+    fde->last_active = std::chrono::steady_clock::now();
+}
+
+std::optional<std::chrono::milliseconds> fdevent_context::CalculatePollDuration() {
+    std::optional<std::chrono::milliseconds> result = std::nullopt;
+    auto now = std::chrono::steady_clock::now();
+    CheckMainThread();
+
+    for (const auto& [fd, fde] : this->installed_fdevents_) {
+        UNUSED(fd);
+        auto timeout_opt = fde->timeout;
+        if (timeout_opt) {
+            auto deadline = fde->last_active + *timeout_opt;
+            auto time_left = duration_cast<std::chrono::milliseconds>(deadline - now);
+            if (time_left < 0ms) {
+                time_left = 0ms;
+            }
+
+            if (!result) {
+                result = time_left;
+            } else {
+                result = std::min(*result, time_left);
+            }
+        }
+    }
+
+    return result;
+}
+
+void fdevent_context::HandleEvents(const std::vector<fdevent_event>& events) {
+    for (const auto& event : events) {
+        invoke_fde(event.fde, event.events);
+    }
+    FlushRunQueue();
+}
+
+void fdevent_context::FlushRunQueue() {
+    // We need to be careful around reentrancy here, since a function we call can queue up another
+    // function.
+    while (true) {
+        std::function<void()> fn;
+        {
+            std::lock_guard<std::mutex> lock(this->run_queue_mutex_);
+            if (this->run_queue_.empty()) {
+                break;
+            }
+            fn = std::move(this->run_queue_.front());
+            this->run_queue_.pop_front();
+        }
+        fn();
+    }
+}
+
+void fdevent_context::CheckMainThread() {
+    if (main_thread_id_) {
+        CHECK_EQ(*main_thread_id_, android::base::GetThreadId());
+    }
+}
+
+void fdevent_context::Run(std::function<void()> fn) {
+    {
+        std::lock_guard<std::mutex> lock(run_queue_mutex_);
+        run_queue_.push_back(std::move(fn));
+    }
+
+    Interrupt();
+}
+
+void fdevent_context::TerminateLoop() {
+    terminate_loop_ = true;
+    Interrupt();
+}
+
+static std::unique_ptr<fdevent_context> fdevent_create_context() {
+#if defined(__linux__)
+    return std::make_unique<fdevent_context_epoll>();
+#else
+    return std::make_unique<fdevent_context_poll>();
+#endif
+}
+
+static auto& g_ambient_fdevent_context =
+        *new std::unique_ptr<fdevent_context>(fdevent_create_context());
+
+static fdevent_context* fdevent_get_ambient() {
+    return g_ambient_fdevent_context.get();
+}
+
+fdevent* fdevent_create(int fd, fd_func func, void* arg) {
+    unique_fd ufd(fd);
+    return fdevent_get_ambient()->Create(std::move(ufd), func, arg);
+}
+
+fdevent* fdevent_create(int fd, fd_func2 func, void* arg) {
+    unique_fd ufd(fd);
+    return fdevent_get_ambient()->Create(std::move(ufd), func, arg);
+}
+
+unique_fd fdevent_release(fdevent* fde) {
+    return fdevent_get_ambient()->Destroy(fde);
+}
+
+void fdevent_destroy(fdevent* fde) {
+    fdevent_get_ambient()->Destroy(fde);
+}
+
+void fdevent_set(fdevent* fde, unsigned events) {
+    fdevent_get_ambient()->Set(fde, events);
+}
+
+void fdevent_add(fdevent* fde, unsigned events) {
+    fdevent_get_ambient()->Add(fde, events);
+}
+
+void fdevent_del(fdevent* fde, unsigned events) {
+    fdevent_get_ambient()->Del(fde, events);
+}
+
+void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout) {
+    fdevent_get_ambient()->SetTimeout(fde, timeout);
+}
+
+void fdevent_run_on_main_thread(std::function<void()> fn) {
+    fdevent_get_ambient()->Run(std::move(fn));
+}
+
+void fdevent_loop() {
+    fdevent_get_ambient()->Loop();
+}
+
+void check_main_thread() {
+    fdevent_get_ambient()->CheckMainThread();
+}
+
+void fdevent_terminate_loop() {
+    fdevent_get_ambient()->TerminateLoop();
+}
+
+size_t fdevent_installed_count() {
+    return fdevent_get_ambient()->InstalledCount();
+}
+
+void fdevent_reset() {
+    g_ambient_fdevent_context = fdevent_create_context();
+}
diff --git a/adb/fdevent/fdevent.h b/adb/fdevent/fdevent.h
new file mode 100644
index 0000000..86814d7
--- /dev/null
+++ b/adb/fdevent/fdevent.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2006 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 __FDEVENT_H
+#define __FDEVENT_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <chrono>
+#include <deque>
+#include <functional>
+#include <mutex>
+#include <optional>
+#include <unordered_map>
+#include <variant>
+
+#include <android-base/thread_annotations.h>
+
+#include "adb_unique_fd.h"
+
+// Events that may be observed
+#define FDE_READ 0x0001
+#define FDE_WRITE 0x0002
+#define FDE_ERROR 0x0004
+#define FDE_TIMEOUT 0x0008
+
+struct fdevent;
+
+typedef void (*fd_func)(int fd, unsigned events, void *userdata);
+typedef void (*fd_func2)(struct fdevent* fde, unsigned events, void* userdata);
+
+void invoke_fde(struct fdevent* fde, unsigned events);
+std::string dump_fde(const fdevent* fde);
+
+struct fdevent_event {
+    fdevent* fde;
+    unsigned events;
+};
+
+struct fdevent_context {
+  public:
+    virtual ~fdevent_context() = default;
+
+    // Allocate and initialize a new fdevent object.
+    fdevent* Create(unique_fd fd, std::variant<fd_func, fd_func2> func, void* arg);
+
+    // Deallocate an fdevent object, returning the file descriptor that was owned by it.
+    // Note that this calls Set, which is a virtual method, so destructors that call this must be
+    // final.
+    unique_fd Destroy(fdevent* fde);
+
+  protected:
+    virtual void Register(fdevent*) {}
+    virtual void Unregister(fdevent*) {}
+
+  public:
+    // Change which events should cause notifications.
+    virtual void Set(fdevent* fde, unsigned events) = 0;
+    void Add(fdevent* fde, unsigned events);
+    void Del(fdevent* fde, unsigned events);
+
+    // Set a timeout on an fdevent.
+    // If no events are triggered by the timeout, an FDE_TIMEOUT will be generated.
+    // Note timeouts are not defused automatically; if a timeout is set on an fdevent, it will
+    // trigger repeatedly every |timeout| ms.
+    void SetTimeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout);
+
+  protected:
+    std::optional<std::chrono::milliseconds> CalculatePollDuration();
+    void HandleEvents(const std::vector<fdevent_event>& events);
+
+  private:
+    // Run all pending functions enqueued via Run().
+    void FlushRunQueue() EXCLUDES(run_queue_mutex_);
+
+  public:
+    // Loop until TerminateLoop is called, handling events.
+    // Implementations should call FlushRunQueue on every iteration, and check the value of
+    // terminate_loop_ to determine whether to stop.
+    virtual void Loop() = 0;
+
+    // Assert that the caller is either running on the context's main thread, or that there is no
+    // active main thread.
+    void CheckMainThread();
+
+    // Queue an operation to be run on the main thread.
+    void Run(std::function<void()> fn);
+
+    // Test-only functionality:
+    void TerminateLoop();
+    virtual size_t InstalledCount() = 0;
+
+  protected:
+    // Interrupt the run loop.
+    virtual void Interrupt() = 0;
+
+    std::optional<uint64_t> main_thread_id_ = std::nullopt;
+    std::atomic<bool> terminate_loop_ = false;
+
+  protected:
+    std::unordered_map<int, fdevent*> installed_fdevents_;
+
+  private:
+    uint64_t fdevent_id_ = 0;
+    std::mutex run_queue_mutex_;
+    std::deque<std::function<void()>> run_queue_ GUARDED_BY(run_queue_mutex_);
+};
+
+struct fdevent {
+    uint64_t id;
+
+    unique_fd fd;
+    int force_eof = 0;
+
+    uint16_t state = 0;
+    std::optional<std::chrono::milliseconds> timeout;
+    std::chrono::steady_clock::time_point last_active;
+
+    std::variant<fd_func, fd_func2> func;
+    void* arg = nullptr;
+};
+
+// Backwards compatibility shims that forward to the global fdevent_context.
+fdevent* fdevent_create(int fd, fd_func func, void* arg);
+fdevent* fdevent_create(int fd, fd_func2 func, void* arg);
+
+unique_fd fdevent_release(fdevent* fde);
+void fdevent_destroy(fdevent* fde);
+
+void fdevent_set(fdevent *fde, unsigned events);
+void fdevent_add(fdevent *fde, unsigned events);
+void fdevent_del(fdevent *fde, unsigned events);
+void fdevent_set_timeout(fdevent* fde, std::optional<std::chrono::milliseconds> timeout);
+void fdevent_loop();
+void check_main_thread();
+
+// Queue an operation to run on the main thread.
+void fdevent_run_on_main_thread(std::function<void()> fn);
+
+// The following functions are used only for tests.
+void fdevent_terminate_loop();
+size_t fdevent_installed_count();
+void fdevent_reset();
+
+#endif
diff --git a/adb/fdevent/fdevent_epoll.cpp b/adb/fdevent/fdevent_epoll.cpp
new file mode 100644
index 0000000..e3d1674
--- /dev/null
+++ b/adb/fdevent/fdevent_epoll.cpp
@@ -0,0 +1,200 @@
+/*
+ * 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 "fdevent_epoll.h"
+
+#if defined(__linux__)
+
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+
+#include <android-base/logging.h>
+#include <android-base/threads.h>
+
+#include "adb_unique_fd.h"
+#include "fdevent.h"
+
+static void fdevent_interrupt(int fd, unsigned, void*) {
+    uint64_t buf;
+    ssize_t rc = TEMP_FAILURE_RETRY(adb_read(fd, &buf, sizeof(buf)));
+    if (rc == -1) {
+        PLOG(FATAL) << "failed to read from fdevent interrupt fd";
+    }
+}
+
+fdevent_context_epoll::fdevent_context_epoll() {
+    epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
+
+    unique_fd interrupt_fd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+    if (interrupt_fd == -1) {
+        PLOG(FATAL) << "failed to create fdevent interrupt eventfd";
+    }
+
+    unique_fd interrupt_fd_dup(fcntl(interrupt_fd.get(), F_DUPFD_CLOEXEC, 3));
+    if (interrupt_fd_dup == -1) {
+        PLOG(FATAL) << "failed to dup fdevent interrupt eventfd";
+    }
+
+    this->interrupt_fd_ = std::move(interrupt_fd_dup);
+    fdevent* fde = this->Create(std::move(interrupt_fd), fdevent_interrupt, nullptr);
+    CHECK(fde != nullptr);
+    this->Add(fde, FDE_READ);
+}
+
+fdevent_context_epoll::~fdevent_context_epoll() {
+    // Destroy calls virtual methods, but this class is final, so that's okay.
+    this->Destroy(this->interrupt_fde_);
+}
+
+static epoll_event calculate_epoll_event(fdevent* fde) {
+    epoll_event result;
+    result.events = 0;
+    if (fde->state & FDE_READ) {
+        result.events |= EPOLLIN;
+    }
+    if (fde->state & FDE_WRITE) {
+        result.events |= EPOLLOUT;
+    }
+    if (fde->state & FDE_ERROR) {
+        result.events |= EPOLLERR;
+    }
+    result.events |= EPOLLRDHUP;
+    result.data.ptr = fde;
+    return result;
+}
+
+void fdevent_context_epoll::Register(fdevent* fde) {
+    epoll_event ev = calculate_epoll_event(fde);
+    if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, fde->fd.get(), &ev) != 0) {
+        PLOG(FATAL) << "failed to register fd " << fde->fd.get() << " with epoll";
+    }
+}
+
+void fdevent_context_epoll::Unregister(fdevent* fde) {
+    if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, fde->fd.get(), nullptr) != 0) {
+        PLOG(FATAL) << "failed to unregister fd " << fde->fd.get() << " with epoll";
+    }
+}
+
+void fdevent_context_epoll::Set(fdevent* fde, unsigned events) {
+    unsigned previous_state = fde->state;
+    fde->state = events;
+
+    // If the state is the same, or only differed by FDE_TIMEOUT, we don't need to modify epoll.
+    if ((previous_state & ~FDE_TIMEOUT) == (events & ~FDE_TIMEOUT)) {
+        return;
+    }
+
+    epoll_event ev = calculate_epoll_event(fde);
+    if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, fde->fd.get(), &ev) != 0) {
+        PLOG(FATAL) << "failed to modify fd " << fde->fd.get() << " with epoll";
+    }
+}
+
+void fdevent_context_epoll::Loop() {
+    main_thread_id_ = android::base::GetThreadId();
+
+    std::vector<fdevent_event> fde_events;
+    std::vector<epoll_event> epoll_events;
+    epoll_events.resize(this->installed_fdevents_.size());
+
+    while (true) {
+        if (terminate_loop_) {
+            break;
+        }
+
+        int rc = -1;
+        while (rc == -1) {
+            std::optional<std::chrono::milliseconds> timeout = CalculatePollDuration();
+            int timeout_ms;
+            if (!timeout) {
+                timeout_ms = -1;
+            } else {
+                timeout_ms = timeout->count();
+            }
+
+            rc = epoll_wait(epoll_fd_.get(), epoll_events.data(), epoll_events.size(), timeout_ms);
+            if (rc == -1 && errno != EINTR) {
+                PLOG(FATAL) << "epoll_wait failed";
+            }
+        }
+
+        auto post_poll = std::chrono::steady_clock::now();
+        std::unordered_map<fdevent*, unsigned> event_map;
+        for (int i = 0; i < rc; ++i) {
+            fdevent* fde = static_cast<fdevent*>(epoll_events[i].data.ptr);
+
+            unsigned events = 0;
+            if (epoll_events[i].events & EPOLLIN) {
+                CHECK(fde->state & FDE_READ);
+                events |= FDE_READ;
+            }
+            if (epoll_events[i].events & EPOLLOUT) {
+                CHECK(fde->state & FDE_WRITE);
+                events |= FDE_WRITE;
+            }
+            if (epoll_events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
+                // We fake a read, as the rest of the code assumes that errors will
+                // be detected at that point.
+                events |= FDE_READ | FDE_ERROR;
+            }
+
+            event_map[fde] = events;
+        }
+
+        for (const auto& [fd, fde] : installed_fdevents_) {
+            unsigned events = 0;
+            if (auto it = event_map.find(fde); it != event_map.end()) {
+                events = it->second;
+            }
+
+            if (events == 0) {
+                if (fde->timeout) {
+                    auto deadline = fde->last_active + *fde->timeout;
+                    if (deadline < post_poll) {
+                        events |= FDE_TIMEOUT;
+                    }
+                }
+            }
+
+            if (events != 0) {
+                LOG(DEBUG) << dump_fde(fde) << " got events " << std::hex << std::showbase
+                           << events;
+                fde_events.push_back({fde, events});
+                fde->last_active = post_poll;
+            }
+        }
+        this->HandleEvents(std::move(fde_events));
+        fde_events.clear();
+    }
+
+    main_thread_id_.reset();
+}
+
+size_t fdevent_context_epoll::InstalledCount() {
+    // We always have an installed fde for interrupt.
+    return this->installed_fdevents_.size() - 1;
+}
+
+void fdevent_context_epoll::Interrupt() {
+    uint64_t i = 1;
+    ssize_t rc = TEMP_FAILURE_RETRY(adb_write(this->interrupt_fd_, &i, sizeof(i)));
+    if (rc != sizeof(i)) {
+        PLOG(FATAL) << "failed to write to fdevent interrupt eventfd";
+    }
+}
+
+#endif  // defined(__linux__)
diff --git a/adb/fdevent/fdevent_epoll.h b/adb/fdevent/fdevent_epoll.h
new file mode 100644
index 0000000..684fa32
--- /dev/null
+++ b/adb/fdevent/fdevent_epoll.h
@@ -0,0 +1,61 @@
+#pragma once
+
+/*
+ * 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.
+ */
+
+#if defined(__linux__)
+
+#include "sysdeps.h"
+
+#include <sys/epoll.h>
+
+#include <deque>
+#include <list>
+#include <mutex>
+#include <unordered_map>
+
+#include <android-base/thread_annotations.h>
+
+#include "adb_unique_fd.h"
+#include "fdevent.h"
+
+struct fdevent_context_epoll final : public fdevent_context {
+    fdevent_context_epoll();
+    virtual ~fdevent_context_epoll();
+
+    virtual void Register(fdevent* fde) final;
+    virtual void Unregister(fdevent* fde) final;
+
+    virtual void Set(fdevent* fde, unsigned events) final;
+
+    virtual void Loop() final;
+    size_t InstalledCount() final;
+
+  protected:
+    virtual void Interrupt() final;
+
+  public:
+    // All operations to fdevent should happen only in the main thread.
+    // That's why we don't need a lock for fdevent.
+    std::unordered_map<int, fdevent*> epoll_node_map_;
+    std::list<fdevent*> pending_list_;
+
+    unique_fd epoll_fd_;
+    unique_fd interrupt_fd_;
+    fdevent* interrupt_fde_ = nullptr;
+};
+
+#endif  // defined(__linux__)
diff --git a/adb/fdevent/fdevent_poll.cpp b/adb/fdevent/fdevent_poll.cpp
new file mode 100644
index 0000000..cc4a7a1
--- /dev/null
+++ b/adb/fdevent/fdevent_poll.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#define TRACE_TAG FDEVENT
+
+#include "sysdeps.h"
+#include "fdevent_poll.h"
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <deque>
+#include <functional>
+#include <list>
+#include <mutex>
+#include <optional>
+#include <unordered_map>
+#include <utility>
+#include <variant>
+#include <vector>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/threads.h>
+
+#include "adb_io.h"
+#include "adb_trace.h"
+#include "adb_unique_fd.h"
+#include "adb_utils.h"
+#include "fdevent.h"
+#include "sysdeps/chrono.h"
+
+static void fdevent_interrupt(int fd, unsigned, void*) {
+    char buf[BUFSIZ];
+    ssize_t rc = TEMP_FAILURE_RETRY(adb_read(fd, buf, sizeof(buf)));
+    if (rc == -1) {
+        PLOG(FATAL) << "failed to read from fdevent interrupt fd";
+    }
+}
+
+fdevent_context_poll::fdevent_context_poll() {
+    int s[2];
+    if (adb_socketpair(s) != 0) {
+        PLOG(FATAL) << "failed to create fdevent interrupt socketpair";
+    }
+
+    if (!set_file_block_mode(s[0], false) || !set_file_block_mode(s[1], false)) {
+        PLOG(FATAL) << "failed to make fdevent interrupt socket nonblocking";
+    }
+
+    this->interrupt_fd_.reset(s[0]);
+    fdevent* fde = this->Create(unique_fd(s[1]), fdevent_interrupt, nullptr);
+    CHECK(fde != nullptr);
+    this->Add(fde, FDE_READ);
+}
+
+fdevent_context_poll::~fdevent_context_poll() {
+    // Destroy calls virtual methods, but this class is final, so that's okay.
+    this->Destroy(this->interrupt_fde_);
+}
+
+void fdevent_context_poll::Set(fdevent* fde, unsigned events) {
+    CheckMainThread();
+    fde->state = events;
+    D("fdevent_set: %s, events = %u", dump_fde(fde).c_str(), events);
+}
+
+static std::string dump_pollfds(const std::vector<adb_pollfd>& pollfds) {
+    std::string result;
+    for (const auto& pollfd : pollfds) {
+        std::string op;
+        if (pollfd.events & POLLIN) {
+            op += "R";
+        }
+        if (pollfd.events & POLLOUT) {
+            op += "W";
+        }
+        android::base::StringAppendF(&result, " %d(%s)", pollfd.fd, op.c_str());
+    }
+    return result;
+}
+
+void fdevent_context_poll::Loop() {
+    main_thread_id_ = android::base::GetThreadId();
+
+    while (true) {
+        if (terminate_loop_) {
+            break;
+        }
+
+        D("--- --- waiting for events");
+        std::vector<adb_pollfd> pollfds;
+        for (const auto& [fd, fde] : this->installed_fdevents_) {
+            adb_pollfd pfd;
+            pfd.fd = fd;
+            pfd.events = 0;
+            if (fde->state & FDE_READ) {
+                pfd.events |= POLLIN;
+            }
+            if (fde->state & FDE_WRITE) {
+                pfd.events |= POLLOUT;
+            }
+            if (fde->state & FDE_ERROR) {
+                pfd.events |= POLLERR;
+            }
+#if defined(__linux__)
+            pfd.events |= POLLRDHUP;
+#endif
+            pfd.revents = 0;
+            pollfds.push_back(pfd);
+        }
+        CHECK_GT(pollfds.size(), 0u);
+        D("poll(), pollfds = %s", dump_pollfds(pollfds).c_str());
+
+        std::optional<std::chrono::milliseconds> timeout = CalculatePollDuration();
+        int timeout_ms;
+        if (!timeout) {
+            timeout_ms = -1;
+        } else {
+            timeout_ms = timeout->count();
+        }
+
+        int ret = adb_poll(pollfds.data(), pollfds.size(), timeout_ms);
+        if (ret == -1) {
+            PLOG(ERROR) << "poll(), ret = " << ret;
+            return;
+        }
+
+        auto post_poll = std::chrono::steady_clock::now();
+        std::vector<fdevent_event> poll_events;
+
+        for (const auto& pollfd : pollfds) {
+            unsigned events = 0;
+            if (pollfd.revents & POLLIN) {
+                events |= FDE_READ;
+            }
+            if (pollfd.revents & POLLOUT) {
+                events |= FDE_WRITE;
+            }
+            if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+                // We fake a read, as the rest of the code assumes that errors will
+                // be detected at that point.
+                events |= FDE_READ | FDE_ERROR;
+            }
+#if defined(__linux__)
+            if (pollfd.revents & POLLRDHUP) {
+                events |= FDE_READ | FDE_ERROR;
+            }
+#endif
+
+            auto it = this->installed_fdevents_.find(pollfd.fd);
+            CHECK(it != this->installed_fdevents_.end());
+            fdevent* fde = it->second;
+
+            if (events == 0) {
+                if (fde->timeout) {
+                    auto deadline = fde->last_active + *fde->timeout;
+                    if (deadline < post_poll) {
+                        events |= FDE_TIMEOUT;
+                    }
+                }
+            }
+
+            if (events != 0) {
+                D("%s got events %x", dump_fde(fde).c_str(), events);
+                poll_events.push_back({fde, events});
+                fde->last_active = post_poll;
+            }
+        }
+        this->HandleEvents(std::move(poll_events));
+    }
+
+    main_thread_id_.reset();
+}
+
+size_t fdevent_context_poll::InstalledCount() {
+    // We always have an installed fde for interrupt.
+    return this->installed_fdevents_.size() - 1;
+}
+
+void fdevent_context_poll::Interrupt() {
+    int rc = adb_write(this->interrupt_fd_, "", 1);
+
+    // It's possible that we get EAGAIN here, if lots of notifications came in while handling.
+    if (rc == 0) {
+        PLOG(FATAL) << "fdevent interrupt fd was closed?";
+    } else if (rc == -1 && errno != EAGAIN) {
+        PLOG(FATAL) << "failed to write to fdevent interrupt fd";
+    }
+}
diff --git a/adb/fdevent/fdevent_poll.h b/adb/fdevent/fdevent_poll.h
new file mode 100644
index 0000000..98abab2
--- /dev/null
+++ b/adb/fdevent/fdevent_poll.h
@@ -0,0 +1,63 @@
+#pragma once
+
+/*
+ * 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 "sysdeps.h"
+
+#include <deque>
+#include <list>
+#include <mutex>
+#include <unordered_map>
+
+#include <android-base/thread_annotations.h>
+
+#include "adb_unique_fd.h"
+#include "fdevent.h"
+
+struct PollNode {
+  fdevent* fde;
+  adb_pollfd pollfd;
+
+  explicit PollNode(fdevent* fde) : fde(fde) {
+      memset(&pollfd, 0, sizeof(pollfd));
+      pollfd.fd = fde->fd.get();
+
+#if defined(__linux__)
+      // Always enable POLLRDHUP, so the host server can take action when some clients disconnect.
+      // Then we can avoid leaving many sockets in CLOSE_WAIT state. See http://b/23314034.
+      pollfd.events = POLLRDHUP;
+#endif
+  }
+};
+
+struct fdevent_context_poll final : public fdevent_context {
+    fdevent_context_poll();
+    virtual ~fdevent_context_poll();
+
+    virtual void Set(fdevent* fde, unsigned events) final;
+
+    virtual void Loop() final;
+
+    virtual size_t InstalledCount() final;
+
+  protected:
+    virtual void Interrupt() final;
+
+  public:
+    unique_fd interrupt_fd_;
+    fdevent* interrupt_fde_ = nullptr;
+};
diff --git a/adb/fdevent_test.cpp b/adb/fdevent/fdevent_test.cpp
similarity index 87%
rename from adb/fdevent_test.cpp
rename to adb/fdevent/fdevent_test.cpp
index 682f061..e06b3b3 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent/fdevent_test.cpp
@@ -118,8 +118,8 @@
 TEST_F(FdeventTest, smoke) {
     for (bool use_new_callback : {true, false}) {
         fdevent_reset();
-        const size_t PIPE_COUNT = 10;
-        const size_t MESSAGE_LOOP_COUNT = 100;
+        const size_t PIPE_COUNT = 512;
+        const size_t MESSAGE_LOOP_COUNT = 10;
         const std::string MESSAGE = "fdevent_test";
         int fd_pair1[2];
         int fd_pair2[2];
@@ -172,44 +172,6 @@
     }
 }
 
-struct InvalidFdArg {
-    fdevent* fde;
-    unsigned expected_events;
-    size_t* happened_event_count;
-};
-
-static void InvalidFdEventCallback(int, unsigned events, void* userdata) {
-    InvalidFdArg* arg = reinterpret_cast<InvalidFdArg*>(userdata);
-    ASSERT_EQ(arg->expected_events, events);
-    fdevent_destroy(arg->fde);
-    if (++*(arg->happened_event_count) == 2) {
-        fdevent_terminate_loop();
-    }
-}
-
-static void InvalidFdThreadFunc() {
-    const int INVALID_READ_FD = std::numeric_limits<int>::max() - 1;
-    size_t happened_event_count = 0;
-    InvalidFdArg read_arg;
-    read_arg.expected_events = FDE_READ | FDE_ERROR;
-    read_arg.happened_event_count = &happened_event_count;
-    read_arg.fde = fdevent_create(INVALID_READ_FD, InvalidFdEventCallback, &read_arg);
-    fdevent_add(read_arg.fde, FDE_READ);
-
-    const int INVALID_WRITE_FD = std::numeric_limits<int>::max();
-    InvalidFdArg write_arg;
-    write_arg.expected_events = FDE_READ | FDE_ERROR;
-    write_arg.happened_event_count = &happened_event_count;
-    write_arg.fde = fdevent_create(INVALID_WRITE_FD, InvalidFdEventCallback, &write_arg);
-    fdevent_add(write_arg.fde, FDE_WRITE);
-    fdevent_loop();
-}
-
-TEST_F(FdeventTest, invalid_fd) {
-    std::thread thread(InvalidFdThreadFunc);
-    thread.join();
-}
-
 TEST_F(FdeventTest, run_on_main_thread) {
     std::vector<int> vec;
 
diff --git a/adb/fdevent_test.h b/adb/fdevent/fdevent_test.h
similarity index 95%
rename from adb/fdevent_test.h
rename to adb/fdevent/fdevent_test.h
index 24bce59..2139d0f 100644
--- a/adb/fdevent_test.h
+++ b/adb/fdevent/fdevent_test.h
@@ -78,8 +78,8 @@
     }
 
     size_t GetAdditionalLocalSocketCount() {
-        // dummy socket installed in PrepareThread() + fdevent_run_on_main_thread socket
-        return 2;
+        // dummy socket installed in PrepareThread()
+        return 1;
     }
 
     void TerminateThread() {
diff --git a/adb/file_sync_protocol.h b/adb/file_sync_protocol.h
index 108639a..508c138 100644
--- a/adb/file_sync_protocol.h
+++ b/adb/file_sync_protocol.h
@@ -21,10 +21,14 @@
 #define ID_LSTAT_V1 MKID('S', 'T', 'A', 'T')
 #define ID_STAT_V2 MKID('S', 'T', 'A', '2')
 #define ID_LSTAT_V2 MKID('L', 'S', 'T', '2')
-#define ID_LIST MKID('L', 'I', 'S', 'T')
+
+#define ID_LIST_V1 MKID('L', 'I', 'S', 'T')
+#define ID_LIST_V2 MKID('L', 'I', 'S', '2')
+#define ID_DENT_V1 MKID('D', 'E', 'N', 'T')
+#define ID_DENT_V2 MKID('D', 'N', 'T', '2')
+
 #define ID_SEND MKID('S', 'E', 'N', 'D')
 #define ID_RECV MKID('R', 'E', 'C', 'V')
-#define ID_DENT MKID('D', 'E', 'N', 'T')
 #define ID_DONE MKID('D', 'O', 'N', 'E')
 #define ID_DATA MKID('D', 'A', 'T', 'A')
 #define ID_OKAY MKID('O', 'K', 'A', 'Y')
@@ -42,7 +46,7 @@
         uint32_t id;
         uint32_t mode;
         uint32_t size;
-        uint32_t time;
+        uint32_t mtime;
     } stat_v1;
     struct __attribute__((packed)) {
         uint32_t id;
@@ -62,17 +66,32 @@
         uint32_t id;
         uint32_t mode;
         uint32_t size;
-        uint32_t time;
+        uint32_t mtime;
         uint32_t namelen;
-    } dent;
+    } dent_v1; // followed by `namelen` bytes of the name.
+    struct __attribute__((packed)) {
+        uint32_t id;
+        uint32_t error;
+        uint64_t dev;
+        uint64_t ino;
+        uint32_t mode;
+        uint32_t nlink;
+        uint32_t uid;
+        uint32_t gid;
+        uint64_t size;
+        int64_t atime;
+        int64_t mtime;
+        int64_t ctime;
+        uint32_t namelen;
+    } dent_v2; // followed by `namelen` bytes of the name.
     struct __attribute__((packed)) {
         uint32_t id;
         uint32_t size;
-    } data;
+    } data; // followed by `size` bytes of data.
     struct __attribute__((packed)) {
         uint32_t id;
         uint32_t msglen;
-    } status;
+    } status; // followed by `msglen` bytes of error message, if id == ID_FAIL.
 };
 
 #define SYNC_DATA_MAX (64 * 1024)
diff --git a/adb/services.cpp b/adb/services.cpp
index 335ffc4..6185aa6 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -100,7 +100,7 @@
     ConnectionState state;
 };
 
-static void wait_for_state(int fd, state_info* sinfo) {
+static void wait_for_state(unique_fd fd, state_info* sinfo) {
     D("wait_for_state %d", sinfo->state);
 
     while (true) {
@@ -122,7 +122,7 @@
         }
 
         if (!is_ambiguous) {
-            adb_pollfd pfd = {.fd = fd, .events = POLLIN};
+            adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
             int rc = adb_poll(&pfd, 1, 100);
             if (rc < 0) {
                 SendFail(fd, error);
@@ -140,7 +140,6 @@
         }
     }
 
-    adb_close(fd);
     D("wait_for_state is done");
 }
 
@@ -203,7 +202,7 @@
         return create_device_tracker(false);
     } else if (name == "track-devices-l") {
         return create_device_tracker(true);
-    } else if (ConsumePrefix(&name, "wait-for-")) {
+    } else if (android::base::ConsumePrefix(&name, "wait-for-")) {
         std::shared_ptr<state_info> sinfo = std::make_shared<state_info>();
         if (sinfo == nullptr) {
             fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
@@ -213,11 +212,11 @@
         sinfo->serial = serial;
         sinfo->transport_id = transport_id;
 
-        if (ConsumePrefix(&name, "local")) {
+        if (android::base::ConsumePrefix(&name, "local")) {
             sinfo->transport_type = kTransportLocal;
-        } else if (ConsumePrefix(&name, "usb")) {
+        } else if (android::base::ConsumePrefix(&name, "usb")) {
             sinfo->transport_type = kTransportUsb;
-        } else if (ConsumePrefix(&name, "any")) {
+        } else if (android::base::ConsumePrefix(&name, "any")) {
             sinfo->transport_type = kTransportAny;
         } else {
             return nullptr;
@@ -241,11 +240,10 @@
             return nullptr;
         }
 
-        unique_fd fd = create_service_thread("wait", [sinfo](int fd) {
-            wait_for_state(fd, sinfo.get());
-        });
+        unique_fd fd = create_service_thread(
+                "wait", [sinfo](unique_fd fd) { wait_for_state(std::move(fd), sinfo.get()); });
         return create_local_socket(std::move(fd));
-    } else if (ConsumePrefix(&name, "connect:")) {
+    } else if (android::base::ConsumePrefix(&name, "connect:")) {
         std::string host(name);
         unique_fd fd = create_service_thread(
                 "connect", std::bind(connect_service, std::placeholders::_1, host));
diff --git a/adb/shell_protocol.h b/adb/shell_protocol.h
index 2c82689..4aab813 100644
--- a/adb/shell_protocol.h
+++ b/adb/shell_protocol.h
@@ -21,6 +21,7 @@
 #include <android-base/macros.h>
 
 #include "adb.h"
+#include "adb_unique_fd.h"
 
 // Class to send and receive shell protocol packets.
 //
@@ -60,7 +61,7 @@
     // should be dynamically allocated on the heap instead.
     //
     // |fd| is an open file descriptor to be used to send or receive packets.
-    explicit ShellProtocol(int fd);
+    explicit ShellProtocol(borrowed_fd fd);
     virtual ~ShellProtocol();
 
     // Returns a pointer to the data buffer.
@@ -103,7 +104,7 @@
         kHeaderSize = sizeof(Id) + sizeof(length_t)
     };
 
-    int fd_;
+    borrowed_fd fd_;
     char buffer_[kBufferSize];
     size_t data_length_ = 0, bytes_left_ = 0;
 
diff --git a/adb/shell_service_protocol.cpp b/adb/shell_service_protocol.cpp
index 13b66ec..95afaff 100644
--- a/adb/shell_service_protocol.cpp
+++ b/adb/shell_service_protocol.cpp
@@ -22,7 +22,7 @@
 
 #include "adb_io.h"
 
-ShellProtocol::ShellProtocol(int fd) : fd_(fd) {
+ShellProtocol::ShellProtocol(borrowed_fd fd) : fd_(fd) {
     buffer_[0] = kIdInvalid;
 }
 
diff --git a/adb/socket.h b/adb/socket.h
index b8c559a..4276851 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -24,7 +24,7 @@
 #include <string>
 
 #include "adb_unique_fd.h"
-#include "fdevent.h"
+#include "fdevent/fdevent.h"
 #include "types.h"
 
 class atransport;
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index de4fff9..d17036c 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -16,6 +16,7 @@
 
 #include "socket_spec.h"
 
+#include <limits>
 #include <string>
 #include <string_view>
 #include <unordered_map>
@@ -28,10 +29,12 @@
 #include <cutils/sockets.h>
 
 #include "adb.h"
+#include "adb_utils.h"
 #include "sysdeps.h"
 
 using namespace std::string_literals;
 
+using android::base::ConsumePrefix;
 using android::base::StringPrintf;
 
 #if defined(__linux__)
@@ -93,7 +96,7 @@
         }
     } else {
         std::string addr(spec.substr(4));
-        port_value = -1;
+        port_value = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
 
         // FIXME: ParseNetAddress rejects port 0. This currently doesn't hurt, because listening
         //        on an address that isn't 'localhost' is unsupported.
@@ -119,6 +122,41 @@
     return true;
 }
 
+int get_host_socket_spec_port(std::string_view spec, std::string* error) {
+    int port;
+    if (spec.starts_with("tcp:")) {
+        if (!parse_tcp_socket_spec(spec, nullptr, &port, nullptr, error)) {
+            return -1;
+        }
+    } else if (spec.starts_with("vsock:")) {
+#if ADB_LINUX
+        std::string spec_str(spec);
+        std::vector<std::string> fragments = android::base::Split(spec_str, ":");
+        if (fragments.size() != 2) {
+            *error = "given vsock server socket string was invalid";
+            return -1;
+        }
+        if (!android::base::ParseInt(fragments[1], &port)) {
+            *error = "could not parse vsock port";
+            errno = EINVAL;
+            return -1;
+        }
+        if (port < 0) {
+            *error = "vsock port was negative.";
+            errno = EINVAL;
+            return -1;
+        }
+#else   // ADB_LINUX
+        *error = "vsock is only supported on linux";
+        return -1;
+#endif  // ADB_LINUX
+    } else {
+        *error = "given socket spec string was invalid";
+        return -1;
+    }
+    return port;
+}
+
 static bool tcp_host_is_local(std::string_view hostname) {
     // FIXME
     return hostname.empty() || hostname == "localhost";
@@ -131,7 +169,7 @@
             return true;
         }
     }
-    return spec.starts_with("tcp:");
+    return spec.starts_with("tcp:") || spec.starts_with("acceptfd:");
 }
 
 bool is_local_socket_spec(std::string_view spec) {
@@ -235,6 +273,9 @@
         *error = "vsock is only supported on linux";
         return false;
 #endif  // ADB_LINUX
+    } else if (address.starts_with("acceptfd:")) {
+        *error = "cannot connect to acceptfd";
+        return false;
     }
 
     for (const auto& it : kLocalSocketTypes) {
@@ -248,6 +289,14 @@
 
             fd->reset(network_local_client(&address[prefix.length()], it.second.socket_namespace,
                                            SOCK_STREAM, error));
+
+            if (fd->get() < 0) {
+                *error =
+                        android::base::StringPrintf("could not connect to %s address '%s'",
+                                                    it.first.c_str(), std::string(address).c_str());
+                return false;
+            }
+
             if (serial) {
                 *serial = address;
             }
@@ -269,10 +318,16 @@
         }
 
         int result;
+#if ADB_HOST
         if (hostname.empty() && gListenAll) {
+#else
+        if (hostname.empty()) {
+#endif
             result = network_inaddr_any_server(port, SOCK_STREAM, error);
         } else if (tcp_host_is_local(hostname)) {
-            result = network_loopback_server(port, SOCK_STREAM, error);
+            result = network_loopback_server(port, SOCK_STREAM, error, true);
+        } else if (hostname == "::1") {
+            result = network_loopback_server(port, SOCK_STREAM, error, false);
         } else {
             // TODO: Implement me.
             *error = "listening on specified hostname currently unsupported";
@@ -314,14 +369,14 @@
         addr.svm_port = port == 0 ? VMADDR_PORT_ANY : port;
         addr.svm_cid = VMADDR_CID_ANY;
         socklen_t addr_len = sizeof(addr);
-        if (bind(serverfd, reinterpret_cast<struct sockaddr*>(&addr), addr_len)) {
+        if (bind(serverfd.get(), reinterpret_cast<struct sockaddr*>(&addr), addr_len)) {
             return -1;
         }
-        if (listen(serverfd, 4)) {
+        if (listen(serverfd.get(), 4)) {
             return -1;
         }
         if (serverfd >= 0 && resolved_port) {
-            if (getsockname(serverfd, reinterpret_cast<sockaddr*>(&addr), &addr_len) == 0) {
+            if (getsockname(serverfd.get(), reinterpret_cast<sockaddr*>(&addr), &addr_len) == 0) {
                 *resolved_port = addr.svm_port;
             } else {
                 return -1;
@@ -332,6 +387,46 @@
         *error = "vsock is only supported on linux";
         return -1;
 #endif  // ADB_LINUX
+    } else if (ConsumePrefix(&spec, "acceptfd:")) {
+#if ADB_WINDOWS
+        *error = "socket activation not supported under Windows";
+        return -1;
+#else
+        // We inherited the socket from some kind of launcher. It's already bound and
+        // listening. Return a copy of the FD instead of the FD itself so we implement the
+        // normal "listen" contract and can succeed more than once.
+        unsigned int fd_u;
+        if (!ParseUint(&fd_u, spec) || fd_u > std::numeric_limits<int>::max()) {
+            *error = "invalid fd";
+            return -1;
+        }
+        int fd = static_cast<int>(fd_u);
+        int flags = get_fd_flags(fd);
+        if (flags < 0) {
+            *error = android::base::StringPrintf("could not get flags of inherited fd %d: '%s'", fd,
+                                                 strerror(errno));
+            return -1;
+        }
+        if (flags & FD_CLOEXEC) {
+            *error = android::base::StringPrintf("fd %d was not inherited from parent", fd);
+            return -1;
+        }
+
+        int dummy_sock_type;
+        socklen_t dummy_sock_type_size = sizeof(dummy_sock_type);
+        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &dummy_sock_type, &dummy_sock_type_size)) {
+            *error = android::base::StringPrintf("fd %d does not refer to a socket", fd);
+            return -1;
+        }
+
+        int new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
+        if (new_fd < 0) {
+            *error = android::base::StringPrintf("could not dup inherited fd %d: '%s'", fd,
+                                                 strerror(errno));
+            return -1;
+        }
+        return new_fd;
+#endif
     }
 
     for (const auto& it : kLocalSocketTypes) {
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
index 7cc2fac..94719c8 100644
--- a/adb/socket_spec.h
+++ b/adb/socket_spec.h
@@ -31,3 +31,5 @@
 
 bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
                            std::string* serial, std::string* error);
+
+int get_host_socket_spec_port(std::string_view spec, std::string* error);
diff --git a/adb/socket_spec_test.cpp b/adb/socket_spec_test.cpp
index f5ec0f1..e9d5270 100644
--- a/adb/socket_spec_test.cpp
+++ b/adb/socket_spec_test.cpp
@@ -18,40 +18,137 @@
 
 #include <string>
 
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
 
-TEST(socket_spec, parse_tcp_socket_spec) {
+TEST(socket_spec, parse_tcp_socket_spec_just_port) {
     std::string hostname, error, serial;
     int port;
     EXPECT_TRUE(parse_tcp_socket_spec("tcp:5037", &hostname, &port, &serial, &error));
     EXPECT_EQ("", hostname);
     EXPECT_EQ(5037, port);
     EXPECT_EQ("", serial);
+}
 
-    // Bad ports:
+TEST(socket_spec, parse_tcp_socket_spec_bad_ports) {
+    std::string hostname, error, serial;
+    int port;
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:-1", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:65536", &hostname, &port, &serial, &error));
+}
 
+TEST(socket_spec, parse_tcp_socket_spec_host_and_port) {
+    std::string hostname, error, serial;
+    int port;
     EXPECT_TRUE(parse_tcp_socket_spec("tcp:localhost:1234", &hostname, &port, &serial, &error));
     EXPECT_EQ("localhost", hostname);
     EXPECT_EQ(1234, port);
     EXPECT_EQ("localhost:1234", serial);
+}
 
-    EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost", &hostname, &port, &serial, &error));
+TEST(socket_spec, parse_tcp_socket_spec_host_no_port) {
+    std::string hostname, error, serial;
+    int port;
+    EXPECT_TRUE(parse_tcp_socket_spec("tcp:localhost", &hostname, &port, &serial, &error));
+    EXPECT_EQ("localhost", hostname);
+    EXPECT_EQ(5555, port);
+    EXPECT_EQ("localhost:5555", serial);
+}
+
+TEST(socket_spec, parse_tcp_socket_spec_host_bad_ports) {
+    std::string hostname, error, serial;
+    int port;
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:-1", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:65536", &hostname, &port, &serial, &error));
+}
 
-    // IPv6:
+TEST(socket_spec, parse_tcp_socket_spec_ipv6_and_port) {
+    std::string hostname, error, serial;
+    int port;
     EXPECT_TRUE(parse_tcp_socket_spec("tcp:[::1]:1234", &hostname, &port, &serial, &error));
     EXPECT_EQ("::1", hostname);
     EXPECT_EQ(1234, port);
     EXPECT_EQ("[::1]:1234", serial);
+}
 
+TEST(socket_spec, parse_tcp_socket_spec_ipv6_no_port) {
+    std::string hostname, error, serial;
+    int port;
+    EXPECT_TRUE(parse_tcp_socket_spec("tcp:::1", &hostname, &port, &serial, &error));
+    EXPECT_EQ("::1", hostname);
+    EXPECT_EQ(5555, port);
+    EXPECT_EQ("[::1]:5555", serial);
+}
+
+TEST(socket_spec, parse_tcp_socket_spec_ipv6_bad_ports) {
+    std::string hostname, error, serial;
+    int port;
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:", &hostname, &port, &serial, &error));
     EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:-1", &hostname, &port, &serial, &error));
-    EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1", &hostname, &port, &serial, &error));
-    EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1:1234", &hostname, &port, &serial, &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port) {
+    std::string error;
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:5555", &error));
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:localhost:5555", &error));
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:[::1]:5555", &error));
+    EXPECT_EQ(5555, get_host_socket_spec_port("vsock:5555", &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port_no_port) {
+    std::string error;
+    EXPECT_EQ(5555, get_host_socket_spec_port("tcp:localhost", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsock:localhost", &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port_bad_ports) {
+    std::string error;
+    EXPECT_EQ(-1, get_host_socket_spec_port("tcp:65536", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("tcp:-5", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsock:-5", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsock:5:5555", &error));
+}
+
+TEST(socket_spec, get_host_socket_spec_port_bad_string) {
+    std::string error;
+    EXPECT_EQ(-1, get_host_socket_spec_port("tcpz:5555", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("vsockz:5555", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("abcd:5555", &error));
+    EXPECT_EQ(-1, get_host_socket_spec_port("abcd", &error));
+}
+
+TEST(socket_spec, socket_spec_listen_connect_tcp) {
+    std::string error, serial;
+    int port;
+    unique_fd server_fd, client_fd;
+    EXPECT_FALSE(socket_spec_connect(&client_fd, "tcp:localhost:7777", &port, &serial, &error));
+    server_fd.reset(socket_spec_listen("tcp:7777", &error, &port));
+    EXPECT_NE(server_fd.get(), -1);
+    EXPECT_TRUE(socket_spec_connect(&client_fd, "tcp:localhost:7777", &port, &serial, &error));
+    EXPECT_NE(client_fd.get(), -1);
+}
+
+TEST(socket_spec, socket_spec_listen_connect_localfilesystem) {
+    std::string error, serial;
+    int port;
+    unique_fd server_fd, client_fd;
+    TemporaryDir sock_dir;
+
+    // Only run this test if the created directory is writable.
+    int result = access(sock_dir.path, W_OK);
+    if (result == 0) {
+        std::string sock_addr =
+                android::base::StringPrintf("localfilesystem:%s/af_unix_socket", sock_dir.path);
+        EXPECT_FALSE(socket_spec_connect(&client_fd, sock_addr, &port, &serial, &error));
+        server_fd.reset(socket_spec_listen(sock_addr, &error, &port));
+        EXPECT_NE(server_fd.get(), -1);
+        EXPECT_TRUE(socket_spec_connect(&client_fd, sock_addr, &port, &serial, &error));
+        EXPECT_NE(client_fd.get(), -1);
+    }
 }
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 5e28f76..1601ff0 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "fdevent.h"
+#include "fdevent/fdevent.h"
 
 #include <gtest/gtest.h>
 
@@ -29,7 +29,7 @@
 
 #include "adb.h"
 #include "adb_io.h"
-#include "fdevent_test.h"
+#include "fdevent/fdevent_test.h"
 #include "socket.h"
 #include "sysdeps.h"
 #include "sysdeps/chrono.h"
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 8a2bf9a..423af67 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -31,6 +31,8 @@
 #include <string>
 #include <vector>
 
+#include <android-base/strings.h>
+
 #if !ADB_HOST
 #include <android-base/properties.h>
 #include <log/log_properties.h>
@@ -123,8 +125,7 @@
         if (rc > 0 && static_cast<size_t>(rc) == s->packet_queue.size()) {
             s->packet_queue.clear();
         } else if (rc > 0) {
-            // TODO: Implement a faster drop_front?
-            s->packet_queue.take_front(rc);
+            s->packet_queue.drop_front(rc);
             fdevent_add(s->fde, FDE_WRITE);
             return SocketFlushResult::TryAgain;
         } else if (rc == -1 && errno == EAGAIN) {
@@ -624,7 +625,8 @@
         return true;
     };
 
-    static constexpr std::string_view prefixes[] = {"usb:", "product:", "model:", "device:"};
+    static constexpr std::string_view prefixes[] = {
+            "usb:", "product:", "model:", "device:", "localfilesystem:"};
     for (std::string_view prefix : prefixes) {
         if (command.starts_with(prefix)) {
             consume(prefix.size());
@@ -755,26 +757,28 @@
 
 #if ADB_HOST
     service = std::string_view(s->smart_socket_data).substr(4);
-    if (ConsumePrefix(&service, "host-serial:")) {
+
+    // TODO: These should be handled in handle_host_request.
+    if (android::base::ConsumePrefix(&service, "host-serial:")) {
         // serial number should follow "host:" and could be a host:port string.
         if (!internal::parse_host_service(&serial, &service, service)) {
             LOG(ERROR) << "SS(" << s->id << "): failed to parse host service: " << service;
             goto fail;
         }
-    } else if (ConsumePrefix(&service, "host-transport-id:")) {
+    } else if (android::base::ConsumePrefix(&service, "host-transport-id:")) {
         if (!ParseUint(&transport_id, service, &service)) {
             LOG(ERROR) << "SS(" << s->id << "): failed to parse host transport id: " << service;
             return -1;
         }
-        if (!ConsumePrefix(&service, ":")) {
+        if (!android::base::ConsumePrefix(&service, ":")) {
             LOG(ERROR) << "SS(" << s->id << "): host-transport-id without command";
             return -1;
         }
-    } else if (ConsumePrefix(&service, "host-usb:")) {
+    } else if (android::base::ConsumePrefix(&service, "host-usb:")) {
         type = kTransportUsb;
-    } else if (ConsumePrefix(&service, "host-local:")) {
+    } else if (android::base::ConsumePrefix(&service, "host-local:")) {
         type = kTransportLocal;
-    } else if (ConsumePrefix(&service, "host:")) {
+    } else if (android::base::ConsumePrefix(&service, "host:")) {
         type = kTransportAny;
     } else {
         service = std::string_view{};
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 15247e7..0c5a6b4 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -33,9 +33,11 @@
 // Include this before open/close/unlink are defined as macros below.
 #include <android-base/errors.h>
 #include <android-base/macros.h>
+#include <android-base/off64_t.h>
 #include <android-base/unique_fd.h>
 #include <android-base/utf8.h>
 
+#include "adb_unique_fd.h"
 #include "sysdeps/errno.h"
 #include "sysdeps/network.h"
 #include "sysdeps/stat.h"
@@ -63,8 +65,6 @@
 #include <memory>   // unique_ptr
 #include <string>
 
-#include "fdevent.h"
-
 #define OS_PATH_SEPARATORS "\\/"
 #define OS_PATH_SEPARATOR '\\'
 #define OS_PATH_SEPARATOR_STR "\\"
@@ -76,66 +76,71 @@
 
 extern int adb_thread_setname(const std::string& name);
 
-static __inline__ void  close_on_exec(int  fd)
-{
+static __inline__ void close_on_exec(borrowed_fd fd) {
     /* nothing really */
 }
 
-extern int  adb_unlink(const char*  path);
-#undef  unlink
-#define unlink  ___xxx_unlink
+extern int adb_unlink(const char* path);
+#undef unlink
+#define unlink ___xxx_unlink
 
 extern int adb_mkdir(const std::string& path, int mode);
-#undef   mkdir
-#define  mkdir  ___xxx_mkdir
+#undef mkdir
+#define mkdir ___xxx_mkdir
 
 // See the comments for the !defined(_WIN32) versions of adb_*().
 extern int adb_open(const char* path, int options);
 extern int adb_creat(const char* path, int mode);
-extern int adb_read(int fd, void* buf, int len);
-extern int adb_write(int fd, const void* buf, int len);
-extern int64_t adb_lseek(int fd, int64_t pos, int where);
-extern int adb_shutdown(int fd, int direction = SHUT_RDWR);
+extern int adb_read(borrowed_fd fd, void* buf, int len);
+extern int adb_pread(borrowed_fd fd, void* buf, int len, off64_t offset);
+extern int adb_write(borrowed_fd fd, const void* buf, int len);
+extern int adb_pwrite(borrowed_fd fd, const void* buf, int len, off64_t offset);
+extern int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where);
+extern int adb_shutdown(borrowed_fd fd, int direction = SHUT_RDWR);
 extern int adb_close(int fd);
 extern int adb_register_socket(SOCKET s);
+extern HANDLE adb_get_os_handle(borrowed_fd fd);
 
 // See the comments for the !defined(_WIN32) version of unix_close().
-static __inline__ int  unix_close(int fd)
-{
+static __inline__ int unix_close(int fd) {
     return close(fd);
 }
-#undef   close
-#define  close   ____xxx_close
+#undef close
+#define close ____xxx_close
 
 // Like unix_read(), but may return EINTR.
-extern int  unix_read_interruptible(int  fd, void*  buf, size_t  len);
+extern int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len);
 
 // See the comments for the !defined(_WIN32) version of unix_read().
-static __inline__ int unix_read(int fd, void* buf, size_t len) {
+static __inline__ int unix_read(borrowed_fd fd, void* buf, size_t len) {
     return TEMP_FAILURE_RETRY(unix_read_interruptible(fd, buf, len));
 }
 
 #undef   read
 #define  read  ___xxx_read
 
+#undef pread
+#define pread ___xxx_pread
+
 // See the comments for the !defined(_WIN32) version of unix_write().
-static __inline__  int  unix_write(int  fd, const void*  buf, size_t  len)
-{
-    return write(fd, buf, len);
+static __inline__ int unix_write(borrowed_fd fd, const void* buf, size_t len) {
+    return write(fd.get(), buf, len);
 }
 #undef   write
 #define  write  ___xxx_write
 
+#undef pwrite
+#define pwrite ___xxx_pwrite
+
 // See the comments for the !defined(_WIN32) version of unix_lseek().
-static __inline__ int unix_lseek(int fd, int pos, int where) {
-    return lseek(fd, pos, where);
+static __inline__ int unix_lseek(borrowed_fd fd, int pos, int where) {
+    return lseek(fd.get(), pos, where);
 }
 #undef lseek
 #define lseek ___xxx_lseek
 
 // See the comments for the !defined(_WIN32) version of adb_open_mode().
-static __inline__ int  adb_open_mode(const char* path, int options, int mode)
-{
+static __inline__ int adb_open_mode(const char* path, int options, int mode) {
     return adb_open(path, options);
 }
 
@@ -152,7 +157,7 @@
 // with |fd| must have GENERIC_READ access (which console FDs have by default).
 // Returns 1 if |fd| is a console FD, 0 otherwise. The value of errno after
 // calling this function is unreliable and should not be used.
-int unix_isatty(int fd);
+int unix_isatty(borrowed_fd fd);
 #define  isatty  ___xxx_isatty
 
 int network_inaddr_any_server(int port, int type, std::string* error);
@@ -168,20 +173,21 @@
 int network_connect(const std::string& host, int port, int type, int timeout,
                     std::string* error);
 
-extern int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen);
+extern int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr, socklen_t* addrlen);
 
 #undef   accept
 #define  accept  ___xxx_accept
 
 // Returns the local port number of a bound socket, or -1 on failure.
-int adb_socket_get_local_port(int fd);
+int adb_socket_get_local_port(borrowed_fd fd);
 
-extern int  adb_setsockopt(int  fd, int  level, int  optname, const void*  optval, socklen_t  optlen);
+extern int adb_setsockopt(borrowed_fd fd, int level, int optname, const void* optval,
+                          socklen_t optlen);
 
 #undef   setsockopt
 #define  setsockopt  ___xxx_setsockopt
 
-extern int  adb_socketpair( int  sv[2] );
+extern int adb_socketpair(int sv[2]);
 
 struct adb_pollfd {
     int fd;
@@ -214,8 +220,7 @@
 extern int adb_fputc(int ch, FILE* stream);
 extern int adb_putchar(int ch);
 extern int adb_puts(const char* buf);
-extern size_t adb_fwrite(const void* ptr, size_t size, size_t nmemb,
-                         FILE* stream);
+extern size_t adb_fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);
 
 extern FILE* adb_fopen(const char* f, const char* m);
 
@@ -344,9 +349,15 @@
     return c == '/';
 }
 
-static __inline__ void  close_on_exec(int  fd)
-{
-    fcntl( fd, F_SETFD, FD_CLOEXEC );
+static __inline__ int get_fd_flags(borrowed_fd fd) {
+    return fcntl(fd.get(), F_GETFD);
+}
+
+static __inline__ void close_on_exec(borrowed_fd fd) {
+    int flags = get_fd_flags(fd);
+    if (flags >= 0 && (flags & FD_CLOEXEC) == 0) {
+        fcntl(fd.get(), F_SETFD, flags | FD_CLOEXEC);
+    }
 }
 
 // Open a file and return a file descriptor that may be used with unix_read(),
@@ -374,12 +385,10 @@
 
 // Similar to the two-argument adb_open(), but takes a mode parameter for file
 // creation. See adb_open() for more info.
-static __inline__ int  adb_open_mode( const char*  pathname, int  options, int  mode )
-{
-    return TEMP_FAILURE_RETRY( open( pathname, options, mode ) );
+static __inline__ int adb_open_mode(const char* pathname, int options, int mode) {
+    return TEMP_FAILURE_RETRY(open(pathname, options, mode));
 }
 
-
 // Open a file and return a file descriptor that may be used with adb_read(),
 // adb_write(), adb_close(), but not unix_read(), unix_write(), unix_close().
 //
@@ -387,23 +396,21 @@
 // sysdeps_win32.cpp) uses Windows native file I/O and bypasses the C Runtime
 // and its CR/LF translation. The returned file descriptor should be used with
 // adb_read(), adb_write(), adb_close(), etc.
-static __inline__ int  adb_open( const char*  pathname, int  options )
-{
-    int  fd = TEMP_FAILURE_RETRY( open( pathname, options ) );
-    if (fd < 0)
-        return -1;
-    close_on_exec( fd );
+static __inline__ int adb_open(const char* pathname, int options) {
+    int fd = TEMP_FAILURE_RETRY(open(pathname, options));
+    if (fd < 0) return -1;
+    close_on_exec(fd);
     return fd;
 }
-#undef   open
-#define  open    ___xxx_open
+#undef open
+#define open ___xxx_open
 
-static __inline__ int adb_shutdown(int fd, int direction = SHUT_RDWR) {
-    return shutdown(fd, direction);
+static __inline__ int adb_shutdown(borrowed_fd fd, int direction = SHUT_RDWR) {
+    return shutdown(fd.get(), direction);
 }
 
-#undef   shutdown
-#define  shutdown   ____xxx_shutdown
+#undef shutdown
+#define shutdown ____xxx_shutdown
 
 // Closes a file descriptor that came from adb_open() or adb_open_mode(), but
 // not designed to take a file descriptor from unix_open(). See the comments
@@ -411,81 +418,97 @@
 __inline__ int adb_close(int fd) {
     return close(fd);
 }
-#undef   close
-#define  close   ____xxx_close
+#undef close
+#define close ____xxx_close
 
 // On Windows, ADB has an indirection layer for file descriptors. If we get a
 // Win32 SOCKET object from an external library, we have to map it in to that
 // indirection layer, which this does.
-__inline__ int  adb_register_socket(int s) {
+__inline__ int adb_register_socket(int s) {
     return s;
 }
 
-static __inline__  int  adb_read(int  fd, void*  buf, size_t  len)
-{
-    return TEMP_FAILURE_RETRY( read( fd, buf, len ) );
+static __inline__ int adb_read(borrowed_fd fd, void* buf, size_t len) {
+    return TEMP_FAILURE_RETRY(read(fd.get(), buf, len));
+}
+
+static __inline__ int adb_pread(int fd, void* buf, size_t len, off64_t offset) {
+#if defined(__APPLE__)
+    return TEMP_FAILURE_RETRY(pread(fd, buf, len, offset));
+#else
+    return TEMP_FAILURE_RETRY(pread64(fd, buf, len, offset));
+#endif
 }
 
 // Like unix_read(), but does not handle EINTR.
-static __inline__ int unix_read_interruptible(int fd, void* buf, size_t len) {
-    return read(fd, buf, len);
+static __inline__ int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len) {
+    return read(fd.get(), buf, len);
 }
 
-#undef   read
-#define  read  ___xxx_read
+#undef read
+#define read ___xxx_read
+#undef pread
+#define pread ___xxx_pread
 
-static __inline__  int  adb_write(int  fd, const void*  buf, size_t  len)
-{
-    return TEMP_FAILURE_RETRY( write( fd, buf, len ) );
+static __inline__ int adb_write(borrowed_fd fd, const void* buf, size_t len) {
+    return TEMP_FAILURE_RETRY(write(fd.get(), buf, len));
 }
+
+static __inline__ int adb_pwrite(int fd, const void* buf, size_t len, off64_t offset) {
+#if defined(__APPLE__)
+    return TEMP_FAILURE_RETRY(pwrite(fd, buf, len, offset));
+#else
+    return TEMP_FAILURE_RETRY(pwrite64(fd, buf, len, offset));
+#endif
+}
+
 #undef   write
 #define  write  ___xxx_write
+#undef pwrite
+#define pwrite ___xxx_pwrite
 
-static __inline__ int64_t adb_lseek(int fd, int64_t pos, int where) {
+static __inline__ int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
 #if defined(__APPLE__)
-    return lseek(fd, pos, where);
+    return lseek(fd.get(), pos, where);
 #else
-    return lseek64(fd, pos, where);
+    return lseek64(fd.get(), pos, where);
 #endif
 }
 #undef lseek
 #define lseek ___xxx_lseek
 
-static __inline__  int    adb_unlink(const char*  path)
-{
-    return  unlink(path);
+static __inline__ int adb_unlink(const char* path) {
+    return unlink(path);
 }
-#undef  unlink
-#define unlink  ___xxx_unlink
+#undef unlink
+#define unlink ___xxx_unlink
 
-static __inline__  int  adb_creat(const char*  path, int  mode)
-{
-    int  fd = TEMP_FAILURE_RETRY( creat( path, mode ) );
+static __inline__ int adb_creat(const char* path, int mode) {
+    int fd = TEMP_FAILURE_RETRY(creat(path, mode));
 
-    if ( fd < 0 )
-        return -1;
+    if (fd < 0) return -1;
 
     close_on_exec(fd);
     return fd;
 }
-#undef   creat
-#define  creat  ___xxx_creat
+#undef creat
+#define creat ___xxx_creat
 
-static __inline__ int unix_isatty(int fd) {
-    return isatty(fd);
+static __inline__ int unix_isatty(borrowed_fd fd) {
+    return isatty(fd.get());
 }
-#define  isatty  ___xxx_isatty
+#define isatty ___xxx_isatty
 
 // Helper for network_* functions.
 inline int _fd_set_error_str(int fd, std::string* error) {
-  if (fd == -1) {
-    *error = strerror(errno);
-  }
-  return fd;
+    if (fd == -1) {
+        *error = strerror(errno);
+    }
+    return fd;
 }
 
 inline int network_inaddr_any_server(int port, int type, std::string* error) {
-  return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
+    return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
 }
 
 inline int network_local_client(const char* name, int namespace_id, int type, std::string* error) {
@@ -498,22 +521,21 @@
 
 int network_connect(const std::string& host, int port, int type, int timeout, std::string* error);
 
-static __inline__ int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
-{
+static __inline__ int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr,
+                                        socklen_t* addrlen) {
     int fd;
 
-    fd = TEMP_FAILURE_RETRY( accept( serverfd, addr, addrlen ) );
-    if (fd >= 0)
-        close_on_exec(fd);
+    fd = TEMP_FAILURE_RETRY(accept(serverfd.get(), addr, addrlen));
+    if (fd >= 0) close_on_exec(fd);
 
     return fd;
 }
 
-#undef   accept
-#define  accept  ___xxx_accept
+#undef accept
+#define accept ___xxx_accept
 
-inline int adb_socket_get_local_port(int fd) {
-    return socket_get_local_port(fd);
+inline int adb_socket_get_local_port(borrowed_fd fd) {
+    return socket_get_local_port(fd.get());
 }
 
 // Operate on a file descriptor returned from unix_open() or a well-known file
@@ -524,10 +546,10 @@
 // Windows implementations (in the ifdef above and in sysdeps_win32.cpp) call
 // into the C Runtime and its configurable CR/LF translation (which is settable
 // via _setmode()).
-#define  unix_read   adb_read
-#define  unix_write  adb_write
+#define unix_read adb_read
+#define unix_write adb_write
 #define unix_lseek adb_lseek
-#define  unix_close  adb_close
+#define unix_close adb_close
 
 static __inline__ int adb_thread_setname(const std::string& name) {
 #ifdef __APPLE__
@@ -542,34 +564,31 @@
 #endif
 }
 
-static __inline__ int  adb_setsockopt( int  fd, int  level, int  optname, const void*  optval, socklen_t  optlen )
-{
-    return setsockopt( fd, level, optname, optval, optlen );
+static __inline__ int adb_setsockopt(borrowed_fd fd, int level, int optname, const void* optval,
+                                     socklen_t optlen) {
+    return setsockopt(fd.get(), level, optname, optval, optlen);
 }
 
-#undef   setsockopt
-#define  setsockopt  ___xxx_setsockopt
+#undef setsockopt
+#define setsockopt ___xxx_setsockopt
 
-static __inline__ int  unix_socketpair( int  d, int  type, int  protocol, int sv[2] )
-{
-    return socketpair( d, type, protocol, sv );
+static __inline__ int unix_socketpair(int d, int type, int protocol, int sv[2]) {
+    return socketpair(d, type, protocol, sv);
 }
 
-static __inline__ int  adb_socketpair( int  sv[2] )
-{
-    int  rc;
+static __inline__ int adb_socketpair(int sv[2]) {
+    int rc;
 
-    rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv );
-    if (rc < 0)
-        return -1;
+    rc = unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
+    if (rc < 0) return -1;
 
-    close_on_exec( sv[0] );
-    close_on_exec( sv[1] );
+    close_on_exec(sv[0]);
+    close_on_exec(sv[1]);
     return 0;
 }
 
-#undef   socketpair
-#define  socketpair   ___xxx_socketpair
+#undef socketpair
+#define socketpair ___xxx_socketpair
 
 typedef struct pollfd adb_pollfd;
 static __inline__ int adb_poll(adb_pollfd* fds, size_t nfds, int timeout) {
@@ -578,29 +597,32 @@
 
 #define poll ___xxx_poll
 
-static __inline__ int  adb_mkdir(const std::string& path, int mode)
-{
+static __inline__ int adb_mkdir(const std::string& path, int mode) {
     return mkdir(path.c_str(), mode);
 }
 
-#undef   mkdir
-#define  mkdir  ___xxx_mkdir
+#undef mkdir
+#define mkdir ___xxx_mkdir
 
 static __inline__ int adb_is_absolute_host_path(const char* path) {
     return path[0] == '/';
 }
 
+static __inline__ int adb_get_os_handle(borrowed_fd fd) {
+    return fd.get();
+}
+
 #endif /* !_WIN32 */
 
-static inline void disable_tcp_nagle(int fd) {
+static inline void disable_tcp_nagle(borrowed_fd fd) {
     int off = 1;
-    adb_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off));
+    adb_setsockopt(fd.get(), IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off));
 }
 
 // Sets TCP socket |fd| to send a keepalive TCP message every |interval_sec| seconds. Set
 // |interval_sec| to 0 to disable keepalives. If keepalives are enabled, the connection will be
 // configured to drop after 10 missed keepalives. Returns true on success.
-bool set_tcp_keepalive(int fd, int interval_sec);
+bool set_tcp_keepalive(borrowed_fd fd, int interval_sec);
 
 #if defined(_WIN32)
 // Win32 defines ERROR, which we don't need, but which conflicts with google3 logging.
diff --git a/adb/sysdeps/network.h b/adb/sysdeps/network.h
index 83ce371..fadd155 100644
--- a/adb/sysdeps/network.h
+++ b/adb/sysdeps/network.h
@@ -19,4 +19,4 @@
 #include <string>
 
 int network_loopback_client(int port, int type, std::string* error);
-int network_loopback_server(int port, int type, std::string* error);
+int network_loopback_server(int port, int type, std::string* error, bool prefer_ipv4);
diff --git a/adb/sysdeps/posix/network.cpp b/adb/sysdeps/posix/network.cpp
index 4de240e..a4d9013 100644
--- a/adb/sysdeps/posix/network.cpp
+++ b/adb/sysdeps/posix/network.cpp
@@ -104,13 +104,13 @@
     socklen_t addrlen = sizeof(addr_storage);
     sockaddr* addr = (ipv6 ? loopback_addr6 : loopback_addr4)(&addr_storage, &addrlen, port);
 
-    if (bind(s, addr, addrlen) != 0) {
+    if (bind(s.get(), addr, addrlen) != 0) {
         set_error(error);
         return -1;
     }
 
     if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
-        if (listen(s, SOMAXCONN) != 0) {
+        if (listen(s.get(), SOMAXCONN) != 0) {
             set_error(error);
             return -1;
         }
@@ -119,12 +119,15 @@
     return s.release();
 }
 
-int network_loopback_server(int port, int type, std::string* error) {
-    int rc = _network_loopback_server(false, port, type, error);
+int network_loopback_server(int port, int type, std::string* error, bool prefer_ipv4) {
+    int rc = -1;
+    if (prefer_ipv4) {
+        rc = _network_loopback_server(false, port, type, error);
+    }
 
-    // Only attempt to listen on IPv6 if IPv4 is unavailable.
+    // Only attempt to listen on IPv6 if IPv4 is unavailable or prefer_ipv4 is false
     // We don't want to start an IPv6 server if there's already an IPv4 one running.
-    if (rc == -1 && (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)) {
+    if (rc == -1 && (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT || !prefer_ipv4)) {
         return _network_loopback_server(true, port, type, error);
     }
     return rc;
diff --git a/adb/sysdeps/uio.h b/adb/sysdeps/uio.h
index d06ef89..ced884b 100644
--- a/adb/sysdeps/uio.h
+++ b/adb/sysdeps/uio.h
@@ -18,6 +18,8 @@
 
 #include <sys/types.h>
 
+#include "adb_unique_fd.h"
+
 #if defined(_WIN32)
 
 // Layout of this struct must match struct WSABUF (verified via static assert in sysdeps_win32.cpp)
@@ -26,13 +28,15 @@
     void* iov_base;
 };
 
-ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt);
+ssize_t adb_writev(borrowed_fd fd, const adb_iovec* iov, int iovcnt);
 
 #else
 
 #include <sys/uio.h>
 using adb_iovec = struct iovec;
-#define adb_writev writev
+inline ssize_t adb_writev(borrowed_fd fd, const adb_iovec* iov, int iovcnt) {
+    return writev(fd.get(), iov, iovcnt);
+}
 
 #endif
 
diff --git a/adb/sysdeps_test.cpp b/adb/sysdeps_test.cpp
index 79cebe6..0f4b39c 100644
--- a/adb/sysdeps_test.cpp
+++ b/adb/sysdeps_test.cpp
@@ -25,6 +25,21 @@
 #include "sysdeps.h"
 #include "sysdeps/chrono.h"
 
+#if defined(_WIN32)
+#include <windows.h>
+static bool IsWine() {
+    HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
+    if (!ntdll) {
+        return false;
+    }
+    return GetProcAddress(ntdll, "wine_get_version") != nullptr;
+}
+#else
+static bool IsWine() {
+    return false;
+}
+#endif
+
 TEST(sysdeps_socketpair, smoke) {
     int fds[2];
     ASSERT_EQ(0, adb_socketpair(fds)) << strerror(errno);
@@ -182,8 +197,10 @@
 
     EXPECT_EQ(1, adb_poll(&pfd, 1, 100));
 
-    // Linux returns POLLIN | POLLHUP, Windows returns just POLLHUP.
-    EXPECT_EQ(POLLHUP, pfd.revents & POLLHUP);
+    if (!IsWine()) {
+        // Linux returns POLLIN | POLLHUP, Windows returns just POLLHUP.
+        EXPECT_EQ(POLLHUP, pfd.revents & POLLHUP);
+    }
 }
 
 TEST_F(sysdeps_poll, fd_count) {
diff --git a/adb/sysdeps_unix.cpp b/adb/sysdeps_unix.cpp
index 4445a44..3fdc917 100644
--- a/adb/sysdeps_unix.cpp
+++ b/adb/sysdeps_unix.cpp
@@ -16,7 +16,7 @@
 
 #include "sysdeps.h"
 
-bool set_tcp_keepalive(int fd, int interval_sec) {
+bool set_tcp_keepalive(borrowed_fd fd, int interval_sec) {
     int enable = (interval_sec > 0);
     if (adb_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable))) {
         return false;
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 4c5d8cb..d9cc36f 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -60,6 +60,7 @@
     int (*_fh_read)(FH, void*, int);
     int (*_fh_write)(FH, const void*, int);
     int (*_fh_writev)(FH, const adb_iovec*, int);
+    intptr_t (*_fh_get_os_handle)(FH);
 } FHClassRec;
 
 static void _fh_file_init(FH);
@@ -68,14 +69,11 @@
 static int _fh_file_read(FH, void*, int);
 static int _fh_file_write(FH, const void*, int);
 static int _fh_file_writev(FH, const adb_iovec*, int);
+static intptr_t _fh_file_get_os_handle(FH f);
 
 static const FHClassRec _fh_file_class = {
-    _fh_file_init,
-    _fh_file_close,
-    _fh_file_lseek,
-    _fh_file_read,
-    _fh_file_write,
-    _fh_file_writev,
+        _fh_file_init,  _fh_file_close,  _fh_file_lseek,         _fh_file_read,
+        _fh_file_write, _fh_file_writev, _fh_file_get_os_handle,
 };
 
 static void _fh_socket_init(FH);
@@ -84,14 +82,11 @@
 static int _fh_socket_read(FH, void*, int);
 static int _fh_socket_write(FH, const void*, int);
 static int _fh_socket_writev(FH, const adb_iovec*, int);
+static intptr_t _fh_socket_get_os_handle(FH f);
 
 static const FHClassRec _fh_socket_class = {
-    _fh_socket_init,
-    _fh_socket_close,
-    _fh_socket_lseek,
-    _fh_socket_read,
-    _fh_socket_write,
-    _fh_socket_writev,
+        _fh_socket_init,  _fh_socket_close,  _fh_socket_lseek,         _fh_socket_read,
+        _fh_socket_write, _fh_socket_writev, _fh_socket_get_os_handle,
 };
 
 #if defined(assert)
@@ -145,16 +140,14 @@
 static  FHRec        _win32_fhs[ WIN32_MAX_FHS ];
 static  int          _win32_fh_next;  // where to start search for free FHRec
 
-static FH
-_fh_from_int( int   fd, const char*   func )
-{
-    FH  f;
+static FH _fh_from_int(borrowed_fd bfd, const char* func) {
+    FH f;
 
+    int fd = bfd.get();
     fd -= WIN32_FH_BASE;
 
     if (fd < 0 || fd >= WIN32_MAX_FHS) {
-        D( "_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE,
-           func );
+        D("_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE, func);
         errno = EBADF;
         return nullptr;
     }
@@ -162,8 +155,7 @@
     f = &_win32_fhs[fd];
 
     if (f->used == 0) {
-        D( "_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE,
-           func );
+        D("_fh_from_int: invalid fd %d passed to %s", fd + WIN32_FH_BASE, func);
         errno = EBADF;
         return nullptr;
     }
@@ -171,20 +163,15 @@
     return f;
 }
 
-
-static int
-_fh_to_int( FH  f )
-{
+static int _fh_to_int(FH f) {
     if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS)
         return (int)(f - _win32_fhs) + WIN32_FH_BASE;
 
     return -1;
 }
 
-static FH
-_fh_alloc( FHClass  clazz )
-{
-    FH   f = nullptr;
+static FH _fh_alloc(FHClass clazz) {
+    FH f = nullptr;
 
     std::lock_guard<std::mutex> lock(_win32_lock);
 
@@ -206,10 +193,7 @@
     return nullptr;
 }
 
-
-static int
-_fh_close( FH   f )
-{
+static int _fh_close(FH f) {
     // Use lock so that closing only happens once and so that _fh_alloc can't
     // allocate a FH that we're in the middle of closing.
     std::lock_guard<std::mutex> lock(_win32_lock);
@@ -342,6 +326,10 @@
     return li.QuadPart;
 }
 
+static intptr_t _fh_file_get_os_handle(FH f) {
+    return reinterpret_cast<intptr_t>(f->u.handle);
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -456,7 +444,7 @@
     return _fh_to_int(f);
 }
 
-int adb_read(int fd, void* buf, int len) {
+int adb_read(borrowed_fd fd, void* buf, int len) {
     FH f = _fh_from_int(fd, __func__);
 
     if (f == nullptr) {
@@ -467,7 +455,27 @@
     return f->clazz->_fh_read(f, buf, len);
 }
 
-int adb_write(int fd, const void* buf, int len) {
+int adb_pread(borrowed_fd fd, void* buf, int len, off64_t offset) {
+    OVERLAPPED overlapped = {};
+    overlapped.Offset = static_cast<DWORD>(offset);
+    overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
+    DWORD bytes_read;
+    if (!::ReadFile(adb_get_os_handle(fd), buf, static_cast<DWORD>(len), &bytes_read,
+                    &overlapped)) {
+        D("adb_pread: could not read %d bytes from FD %d", len, fd.get());
+        switch (::GetLastError()) {
+            case ERROR_IO_PENDING:
+                errno = EAGAIN;
+                return -1;
+            default:
+                errno = EINVAL;
+                return -1;
+        }
+    }
+    return static_cast<int>(bytes_read);
+}
+
+int adb_write(borrowed_fd fd, const void* buf, int len) {
     FH f = _fh_from_int(fd, __func__);
 
     if (f == nullptr) {
@@ -478,7 +486,7 @@
     return f->clazz->_fh_write(f, buf, len);
 }
 
-ssize_t adb_writev(int fd, const adb_iovec* iov, int iovcnt) {
+ssize_t adb_writev(borrowed_fd fd, const adb_iovec* iov, int iovcnt) {
     FH f = _fh_from_int(fd, __func__);
 
     if (f == nullptr) {
@@ -489,7 +497,26 @@
     return f->clazz->_fh_writev(f, iov, iovcnt);
 }
 
-int64_t adb_lseek(int fd, int64_t pos, int where) {
+int adb_pwrite(borrowed_fd fd, const void* buf, int len, off64_t offset) {
+    OVERLAPPED params = {};
+    params.Offset = static_cast<DWORD>(offset);
+    params.OffsetHigh = static_cast<DWORD>(offset >> 32);
+    DWORD bytes_written = 0;
+    if (!::WriteFile(adb_get_os_handle(fd), buf, len, &bytes_written, &params)) {
+        D("adb_pwrite: could not write %d bytes to FD %d", len, fd.get());
+        switch (::GetLastError()) {
+            case ERROR_IO_PENDING:
+                errno = EAGAIN;
+                return -1;
+            default:
+                errno = EINVAL;
+                return -1;
+        }
+    }
+    return static_cast<int>(bytes_written);
+}
+
+int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
     FH f = _fh_from_int(fd, __func__);
     if (!f) {
         errno = EBADF;
@@ -511,6 +538,20 @@
     return 0;
 }
 
+HANDLE adb_get_os_handle(borrowed_fd fd) {
+    FH f = _fh_from_int(fd, __func__);
+
+    if (!f) {
+        errno = EBADF;
+        return nullptr;
+    }
+
+    D("adb_get_os_handle: %s", f->name);
+    const intptr_t intptr_handle = f->clazz->_fh_get_os_handle(f);
+    const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle);
+    return handle;
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -621,15 +662,6 @@
 
 static int _fh_socket_close(FH f) {
     if (f->fh_socket != INVALID_SOCKET) {
-        /* gently tell any peer that we're closing the socket */
-        if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
-            // If the socket is not connected, this returns an error. We want to
-            // minimize logging spam, so don't log these errors for now.
-#if 0
-            D("socket shutdown failed: %s",
-              android::base::SystemErrorCodeToString(WSAGetLastError()).c_str());
-#endif
-        }
         if (closesocket(f->fh_socket) == SOCKET_ERROR) {
             // Don't set errno here, since adb_close will ignore it.
             const DWORD err = WSAGetLastError();
@@ -708,12 +740,16 @@
               android::base::SystemErrorCodeToString(err).c_str());
         }
         _socket_set_errno(err);
-        result = -1;
+        return -1;
     }
     CHECK_GE(static_cast<DWORD>(std::numeric_limits<int>::max()), bytes_written);
     return static_cast<int>(bytes_written);
 }
 
+static intptr_t _fh_socket_get_os_handle(FH f) {
+    return f->u.socket;
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -884,7 +920,8 @@
     return fd;
 }
 
-int network_loopback_server(int port, int type, std::string* error) {
+int network_loopback_server(int port, int type, std::string* error, bool prefer_ipv4) {
+    // TODO implement IPv6 support on windows
     return _network_server(port, type, INADDR_LOOPBACK, error);
 }
 
@@ -973,11 +1010,11 @@
 }
 
 #undef accept
-int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t* addrlen) {
+int adb_socket_accept(borrowed_fd serverfd, struct sockaddr* addr, socklen_t* addrlen) {
     FH serverfh = _fh_from_int(serverfd, __func__);
 
     if (!serverfh || serverfh->clazz != &_fh_socket_class) {
-        D("adb_socket_accept: invalid fd %d", serverfd);
+        D("adb_socket_accept: invalid fd %d", serverfd.get());
         errno = EBADF;
         return -1;
     }
@@ -992,7 +1029,7 @@
     fh->fh_socket = accept(serverfh->fh_socket, addr, addrlen);
     if (fh->fh_socket == INVALID_SOCKET) {
         const DWORD err = WSAGetLastError();
-        LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd
+        LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd.get()
                    << " failed: " + android::base::SystemErrorCodeToString(err);
         _socket_set_errno(err);
         return -1;
@@ -1000,16 +1037,16 @@
 
     const int fd = _fh_to_int(fh.get());
     snprintf(fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name);
-    D("adb_socket_accept on fd %d returns fd %d", serverfd, fd);
+    D("adb_socket_accept on fd %d returns fd %d", serverfd.get(), fd);
     fh.release();
     return fd;
 }
 
-int adb_setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen) {
+int adb_setsockopt(borrowed_fd fd, int level, int optname, const void* optval, socklen_t optlen) {
     FH fh = _fh_from_int(fd, __func__);
 
     if (!fh || fh->clazz != &_fh_socket_class) {
-        D("adb_setsockopt: invalid fd %d", fd);
+        D("adb_setsockopt: invalid fd %d", fd.get());
         errno = EBADF;
         return -1;
     }
@@ -1022,7 +1059,7 @@
         setsockopt(fh->fh_socket, level, optname, reinterpret_cast<const char*>(optval), optlen);
     if (result == SOCKET_ERROR) {
         const DWORD err = WSAGetLastError();
-        D("adb_setsockopt: setsockopt on fd %d level %d optname %d failed: %s\n", fd, level,
+        D("adb_setsockopt: setsockopt on fd %d level %d optname %d failed: %s\n", fd.get(), level,
           optname, android::base::SystemErrorCodeToString(err).c_str());
         _socket_set_errno(err);
         result = -1;
@@ -1030,11 +1067,11 @@
     return result;
 }
 
-int adb_getsockname(int fd, struct sockaddr* sockaddr, socklen_t* optlen) {
+static int adb_getsockname(borrowed_fd fd, struct sockaddr* sockaddr, socklen_t* optlen) {
     FH fh = _fh_from_int(fd, __func__);
 
     if (!fh || fh->clazz != &_fh_socket_class) {
-        D("adb_getsockname: invalid fd %d", fd);
+        D("adb_getsockname: invalid fd %d", fd.get());
         errno = EBADF;
         return -1;
     }
@@ -1042,7 +1079,7 @@
     int result = getsockname(fh->fh_socket, sockaddr, optlen);
     if (result == SOCKET_ERROR) {
         const DWORD err = WSAGetLastError();
-        D("adb_getsockname: setsockopt on fd %d failed: %s\n", fd,
+        D("adb_getsockname: setsockopt on fd %d failed: %s\n", fd.get(),
           android::base::SystemErrorCodeToString(err).c_str());
         _socket_set_errno(err);
         result = -1;
@@ -1050,7 +1087,7 @@
     return result;
 }
 
-int adb_socket_get_local_port(int fd) {
+int adb_socket_get_local_port(borrowed_fd fd) {
     sockaddr_storage addr_storage;
     socklen_t addr_len = sizeof(addr_storage);
 
@@ -1068,11 +1105,11 @@
     return ntohs(reinterpret_cast<sockaddr_in*>(&addr_storage)->sin_port);
 }
 
-int adb_shutdown(int fd, int direction) {
+int adb_shutdown(borrowed_fd fd, int direction) {
     FH f = _fh_from_int(fd, __func__);
 
     if (!f || f->clazz != &_fh_socket_class) {
-        D("adb_shutdown: invalid fd %d", fd);
+        D("adb_shutdown: invalid fd %d", fd.get());
         errno = EBADF;
         return -1;
     }
@@ -1080,7 +1117,7 @@
     D("adb_shutdown: %s", f->name);
     if (shutdown(f->fh_socket, direction) == SOCKET_ERROR) {
         const DWORD err = WSAGetLastError();
-        D("socket shutdown fd %d failed: %s", fd,
+        D("socket shutdown fd %d failed: %s", fd.get(),
           android::base::SystemErrorCodeToString(err).c_str());
         _socket_set_errno(err);
         return -1;
@@ -1096,7 +1133,7 @@
     int local_port = -1;
     std::string error;
 
-    server = network_loopback_server(0, SOCK_STREAM, &error);
+    server = network_loopback_server(0, SOCK_STREAM, &error, true);
     if (server < 0) {
         D("adb_socketpair: failed to create server: %s", error.c_str());
         goto fail;
@@ -1138,12 +1175,12 @@
     return -1;
 }
 
-bool set_file_block_mode(int fd, bool block) {
+bool set_file_block_mode(borrowed_fd fd, bool block) {
     FH fh = _fh_from_int(fd, __func__);
 
     if (!fh || !fh->used) {
         errno = EBADF;
-        D("Setting nonblocking on bad file descriptor %d", fd);
+        D("Setting nonblocking on bad file descriptor %d", fd.get());
         return false;
     }
 
@@ -1152,22 +1189,22 @@
         if (ioctlsocket(fh->u.socket, FIONBIO, &x) != 0) {
             int error = WSAGetLastError();
             _socket_set_errno(error);
-            D("Setting %d nonblocking failed (%d)", fd, error);
+            D("Setting %d nonblocking failed (%d)", fd.get(), error);
             return false;
         }
         return true;
     } else {
         errno = ENOTSOCK;
-        D("Setting nonblocking on non-socket %d", fd);
+        D("Setting nonblocking on non-socket %d", fd.get());
         return false;
     }
 }
 
-bool set_tcp_keepalive(int fd, int interval_sec) {
+bool set_tcp_keepalive(borrowed_fd fd, int interval_sec) {
     FH fh = _fh_from_int(fd, __func__);
 
     if (!fh || fh->clazz != &_fh_socket_class) {
-        D("set_tcp_keepalive(%d) failed: invalid fd", fd);
+        D("set_tcp_keepalive(%d) failed: invalid fd", fd.get());
         errno = EBADF;
         return false;
     }
@@ -1181,7 +1218,7 @@
     if (WSAIoctl(fh->fh_socket, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), nullptr, 0,
                  &bytes_returned, nullptr, nullptr) != 0) {
         const DWORD err = WSAGetLastError();
-        D("set_tcp_keepalive(%d) failed: %s", fd,
+        D("set_tcp_keepalive(%d) failed: %s", fd.get(),
           android::base::SystemErrorCodeToString(err).c_str());
         _socket_set_errno(err);
         return false;
@@ -1228,12 +1265,12 @@
 // Returns a console HANDLE if |fd| is a console, otherwise returns nullptr.
 // If a valid HANDLE is returned and |mode| is not null, |mode| is also filled
 // with the console mode. Requires GENERIC_READ access to the underlying HANDLE.
-static HANDLE _get_console_handle(int fd, DWORD* mode=nullptr) {
+static HANDLE _get_console_handle(borrowed_fd fd, DWORD* mode = nullptr) {
     // First check isatty(); this is very fast and eliminates most non-console
     // FDs, but returns 1 for both consoles and character devices like NUL.
 #pragma push_macro("isatty")
 #undef isatty
-    if (!isatty(fd)) {
+    if (!isatty(fd.get())) {
         return nullptr;
     }
 #pragma pop_macro("isatty")
@@ -1241,7 +1278,7 @@
     // To differentiate between character devices and consoles we need to get
     // the underlying HANDLE and use GetConsoleMode(), which is what requires
     // GENERIC_READ permissions.
-    const intptr_t intptr_handle = _get_osfhandle(fd);
+    const intptr_t intptr_handle = _get_osfhandle(fd.get());
     if (intptr_handle == -1) {
         return nullptr;
     }
@@ -1265,7 +1302,7 @@
     return _get_console_handle(fd);
 }
 
-int unix_isatty(int fd) {
+int unix_isatty(borrowed_fd fd) {
     return _get_console_handle(fd) ? 1 : 0;
 }
 
@@ -1645,7 +1682,7 @@
 
 // Prefix the len bytes in buf with the escape character, and then return the
 // new buffer length.
-size_t _escape_prefix(char* const buf, const size_t len) {
+static size_t _escape_prefix(char* const buf, const size_t len) {
     // If nothing to prefix, don't do anything. We might be called with
     // len == 0, if alt was held down with a dead key which produced nothing.
     if (len == 0) {
@@ -2073,7 +2110,7 @@
 }
 
 // Called by 'adb shell' and 'adb exec-in' (via unix_read()) to read from stdin.
-int unix_read_interruptible(int fd, void* buf, size_t len) {
+int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len) {
     if ((fd == STDIN_FILENO) && (_console_handle != nullptr)) {
         // If it is a request to read from stdin, and stdin_raw_init() has been
         // called, and it successfully configured the console, then read from
@@ -2093,7 +2130,7 @@
         // plain read() in favor of unix_read() or adb_read().
 #pragma push_macro("read")
 #undef read
-        return read(fd, buf, len);
+        return read(fd.get(), buf, len);
 #pragma pop_macro("read")
     }
 }
@@ -2617,7 +2654,9 @@
 extern "C" int wmain(int argc, wchar_t **argv) {
     // Convert args from UTF-16 to UTF-8 and pass that to main().
     NarrowArgs narrow_args(argc, argv);
-    return main(argc, narrow_args.data());
+
+    // Avoid destructing NarrowArgs: argv might have been mutated to point to string literals.
+    _exit(main(argc, narrow_args.data()));
 }
 
 // Shadow UTF-8 environment variable name/value pairs that are created from
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 8272722..3d6de26 100755
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -281,6 +281,37 @@
             subprocess.check_output(["adb", "-P", str(port), "kill-server"],
                                     stderr=subprocess.STDOUT)
 
+    @unittest.skipUnless(
+        os.name == "posix",
+        "adb doesn't yet support IPv6 on Windows",
+    )
+    def test_starts_on_ipv6_localhost(self):
+        """
+        Tests that the server can start up on ::1 and that it's accessible
+        """
+        server_port = 5037
+        # Kill any existing server on this non-default port.
+        subprocess.check_output(
+            ["adb", "-P", str(server_port), "kill-server"],
+            stderr=subprocess.STDOUT,
+        )
+        try:
+            subprocess.check_output(
+                ["adb", "-L", "tcp:[::1]:{}".format(server_port), "server"],
+                stderr=subprocess.STDOUT,
+            )
+            with fake_adbd() as (port, _):
+                with adb_connect(self, serial="localhost:{}".format(port)):
+                    pass
+        finally:
+            # If we started a server, kill it.
+            subprocess.check_output(
+                ["adb", "-P", str(server_port), "kill-server"],
+                stderr=subprocess.STDOUT,
+            )
+
+
+
 
 class EmulatorTest(unittest.TestCase):
     """Tests for the emulator connection."""
diff --git a/adb/test_device.py b/adb/test_device.py
index f95a5b3..083adce 100755
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -139,6 +139,25 @@
         msg = self.device.forward_list()
         self.assertEqual('', msg.strip())
 
+    def test_forward_old_protocol(self):
+        serialno = subprocess.check_output(self.device.adb_cmd + ['get-serialno']).strip()
+
+        msg = self.device.forward_list()
+        self.assertEqual('', msg.strip(),
+                         'Forwarding list must be empty to run this test.')
+
+        s = socket.create_connection(("localhost", 5037))
+        service = b"host-serial:%s:forward:tcp:5566;tcp:6655" % serialno
+        cmd = b"%04x%s" % (len(service), service)
+        s.sendall(cmd)
+
+        msg = self.device.forward_list()
+        self.assertTrue(re.search(r'tcp:5566.+tcp:6655', msg))
+
+        self.device.forward_remove_all()
+        msg = self.device.forward_list()
+        self.assertEqual('', msg.strip())
+
     def test_forward_tcp_port_0(self):
         self.assertEqual('', self.device.forward_list().strip(),
                          'Forwarding list must be empty to run this test.')
@@ -517,6 +536,36 @@
         for i, success in result.iteritems():
             self.assertTrue(success)
 
+    def disabled_test_parallel(self):
+        """Spawn a bunch of `adb shell` instances in parallel.
+
+        This was broken historically due to the use of select, which only works
+        for fds that are numerically less than 1024.
+
+        Bug: http://b/141955761"""
+
+        n_procs = 2048
+        procs = dict()
+        for i in xrange(0, n_procs):
+            procs[i] = subprocess.Popen(
+                ['adb', 'shell', 'read foo; echo $foo; read rc; exit $rc'],
+                stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE
+            )
+
+        for i in xrange(0, n_procs):
+            procs[i].stdin.write("%d\n" % i)
+
+        for i in xrange(0, n_procs):
+            response = procs[i].stdout.readline()
+            assert(response == "%d\n" % i)
+
+        for i in xrange(0, n_procs):
+            procs[i].stdin.write("%d\n" % (i % 256))
+
+        for i in xrange(0, n_procs):
+            assert(procs[i].wait() == i % 256)
+
 
 class ArgumentEscapingTest(DeviceTest):
     def test_shell_escaping(self):
@@ -884,6 +933,20 @@
             remote_path += '/filename'
             self.device.push(local=tmp_file.name, remote=remote_path)
 
+    def disabled_test_push_multiple_slash_root(self):
+        """Regression test for pushing to //data/local/tmp.
+
+        Bug: http://b/141311284
+
+        Disabled because this broken on the adbd side as well: b/141943968
+        """
+        with tempfile.NamedTemporaryFile() as tmp_file:
+            tmp_file.write('\0' * 1024 * 1024)
+            tmp_file.flush()
+            remote_path = '/' + self.DEVICE_TEMP_DIR + '/test_push_multiple_slash_root'
+            self.device.shell(['rm', '-rf', remote_path])
+            self.device.push(local=tmp_file.name, remote=remote_path)
+
     def _test_pull(self, remote_file, checksum):
         tmp_write = tempfile.NamedTemporaryFile(mode='wb', delete=False)
         tmp_write.close()
diff --git a/libmeminfo/libdmabufinfo/tools/Android.bp b/adb/tools/Android.bp
similarity index 67%
copy from libmeminfo/libdmabufinfo/tools/Android.bp
copy to adb/tools/Android.bp
index 224b68e..71e32b7 100644
--- a/libmeminfo/libdmabufinfo/tools/Android.bp
+++ b/adb/tools/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 The Android Open Source Project
+// Copyright (C) 2017 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.
@@ -12,19 +12,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_binary {
-    name: "dmabuf_dump",
-    cflags: [
-        "-Wall",
-        "-Werror",
+cc_binary_host {
+    name: "check_ms_os_desc",
+
+    defaults: ["adb_defaults"],
+
+    srcs: [
+        "check_ms_os_desc.cpp",
     ],
 
-    srcs: ["dmabuf_dump.cpp"],
-    shared_libs: [
-        "libbase",
-    ],
     static_libs: [
-        "libdmabufinfo",
+        "libbase",
+        "libusb",
     ],
-    product_specific: true,
-}
\ No newline at end of file
+
+    stl: "libc++_static",
+
+    dist: {
+        targets: [
+            "sdk",
+        ],
+    },
+}
diff --git a/adb/tools/check_ms_os_desc.cpp b/adb/tools/check_ms_os_desc.cpp
new file mode 100644
index 0000000..8743ff7
--- /dev/null
+++ b/adb/tools/check_ms_os_desc.cpp
@@ -0,0 +1,266 @@
+/*
+ * 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 <err.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <optional>
+#include <string>
+#include <vector>
+
+#include <libusb/libusb.h>
+
+static bool is_adb_device(libusb_device* device) {
+    libusb_device_descriptor device_desc;
+    libusb_get_device_descriptor(device, &device_desc);
+    if (device_desc.bDeviceClass != 0) {
+        return false;
+    }
+
+    libusb_config_descriptor* config_desc;
+    int rc = libusb_get_active_config_descriptor(device, &config_desc);
+    if (rc != 0) {
+        fprintf(stderr, "failed to get config descriptor for device %u:%u: %s\n",
+                libusb_get_bus_number(device), libusb_get_port_number(device),
+                libusb_error_name(rc));
+        return false;
+    }
+
+    for (size_t i = 0; i < config_desc->bNumInterfaces; ++i) {
+        const libusb_interface* interface = &config_desc->interface[i];
+        for (int j = 0; j < interface->num_altsetting; ++j) {
+            const libusb_interface_descriptor* interface_descriptor = &interface->altsetting[j];
+            if (interface_descriptor->bInterfaceClass == 0xff &&
+                interface_descriptor->bInterfaceSubClass == 0x42 &&
+                interface_descriptor->bInterfaceProtocol == 1) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+static std::optional<std::vector<uint8_t>> get_descriptor(libusb_device_handle* handle,
+                                                          uint8_t type, uint8_t index,
+                                                          uint16_t length) {
+    std::vector<uint8_t> result;
+    result.resize(length);
+    int rc = libusb_get_descriptor(handle, type, index, result.data(), result.size());
+    if (rc < 0) {
+        fprintf(stderr, "libusb_get_descriptor failed: %s\n", libusb_error_name(rc));
+        return std::nullopt;
+    }
+    result.resize(rc);
+    return result;
+}
+
+static std::optional<std::string> get_string_descriptor(libusb_device_handle* handle,
+                                                        uint8_t index) {
+    std::string result;
+    result.resize(4096);
+    int rc = libusb_get_string_descriptor_ascii(
+            handle, index, reinterpret_cast<uint8_t*>(result.data()), result.size());
+    if (rc < 0) {
+        fprintf(stderr, "libusb_get_string_descriptor_ascii failed: %s\n", libusb_error_name(rc));
+        return std::nullopt;
+    }
+    result.resize(rc);
+    return result;
+}
+
+static void check_ms_os_desc_v1(libusb_device_handle* device_handle, const std::string& serial) {
+    auto os_desc = get_descriptor(device_handle, 0x03, 0xEE, 0x12);
+    if (!os_desc) {
+        errx(1, "failed to retrieve MS OS descriptor");
+    }
+
+    if (os_desc->size() != 0x12) {
+        errx(1, "os descriptor size mismatch");
+    }
+
+    if (memcmp(os_desc->data() + 2, u"MSFT100\0", 14) != 0) {
+        errx(1, "os descriptor signature mismatch");
+    }
+
+    uint8_t vendor_code = (*os_desc)[16];
+    uint8_t pad = (*os_desc)[17];
+
+    if (pad != 0) {
+        errx(1, "os descriptor padding non-zero");
+    }
+
+    std::vector<uint8_t> data;
+    data.resize(0x10);
+    int rc = libusb_control_transfer(device_handle, 0xC0, vendor_code, 0x00, 0x04, data.data(),
+                                     data.size(), 0);
+    if (rc != 0x10) {
+        errx(1, "failed to retrieve MS OS v1 compat descriptor header: %s", libusb_error_name(rc));
+    }
+
+    struct __attribute__((packed)) ms_os_desc_v1_header {
+        uint32_t dwLength;
+        uint16_t bcdVersion;
+        uint16_t wIndex;
+        uint8_t bCount;
+        uint8_t reserved[7];
+    };
+    static_assert(sizeof(ms_os_desc_v1_header) == 0x10);
+
+    ms_os_desc_v1_header hdr;
+    memcpy(&hdr, data.data(), data.size());
+
+    data.resize(hdr.dwLength);
+    rc = libusb_control_transfer(device_handle, 0xC0, vendor_code, 0x00, 0x04, data.data(),
+                                 data.size(), 0);
+    if (static_cast<size_t>(rc) != data.size()) {
+        errx(1, "failed to retrieve MS OS v1 compat descriptor: %s", libusb_error_name(rc));
+    }
+
+    memcpy(&hdr, data.data(), data.size());
+
+    struct __attribute__((packed)) ms_os_desc_v1_function {
+        uint8_t bFirstInterfaceNumber;
+        uint8_t reserved1;
+        uint8_t compatibleID[8];
+        uint8_t subCompatibleID[8];
+        uint8_t reserved2[6];
+    };
+
+    if (sizeof(ms_os_desc_v1_header) + hdr.bCount * sizeof(ms_os_desc_v1_function) != data.size()) {
+        errx(1, "MS OS v1 compat descriptor size mismatch");
+    }
+
+    for (int i = 0; i < hdr.bCount; ++i) {
+        ms_os_desc_v1_function function;
+        memcpy(&function,
+               data.data() + sizeof(ms_os_desc_v1_header) + i * sizeof(ms_os_desc_v1_function),
+               sizeof(function));
+        if (memcmp("WINUSB\0\0", function.compatibleID, 8) == 0) {
+            return;
+        }
+    }
+
+    errx(1, "failed to find v1 MS OS descriptor specifying WinUSB for device %s", serial.c_str());
+}
+
+static void check_ms_os_desc_v2(libusb_device_handle* device_handle, const std::string& serial) {
+    libusb_bos_descriptor* bos;
+    int rc = libusb_get_bos_descriptor(device_handle, &bos);
+
+    if (rc != 0) {
+        fprintf(stderr, "failed to get bos descriptor for device %s\n", serial.c_str());
+        return;
+    }
+
+    for (size_t i = 0; i < bos->bNumDeviceCaps; ++i) {
+        libusb_bos_dev_capability_descriptor* desc = bos->dev_capability[i];
+        if (desc->bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) {
+            errx(1, "invalid BOS descriptor type: %d", desc->bDescriptorType);
+        }
+
+        if (desc->bDevCapabilityType != 0x05 /* PLATFORM */) {
+            fprintf(stderr, "skipping non-platform dev capability: %#02x\n",
+                    desc->bDevCapabilityType);
+            continue;
+        }
+
+        if (desc->bLength < sizeof(*desc) + 16) {
+            errx(1, "received device capability descriptor not long enough to contain a UUID?");
+        }
+
+        char uuid[16];
+        memcpy(uuid, desc->dev_capability_data, 16);
+
+        constexpr uint8_t ms_os_uuid[16] = {0xD8, 0xDD, 0x60, 0xDF, 0x45, 0x89, 0x4C, 0xC7,
+                                            0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F};
+        if (memcmp(uuid, ms_os_uuid, 16) != 0) {
+            fprintf(stderr, "skipping unknown UUID\n");
+            continue;
+        }
+
+        size_t data_length = desc->bLength - sizeof(*desc) - 16;
+        fprintf(stderr, "found MS OS 2.0 descriptor, length = %zu\n", data_length);
+
+        // Linux does not appear to support MS OS 2.0 Descriptors.
+        // TODO: If and when it does, verify that we're emitting them properly.
+    }
+}
+
+int main(int argc, char** argv) {
+    libusb_context* ctx;
+    if (libusb_init(&ctx) != 0) {
+        errx(1, "failed to initialize libusb context");
+    }
+
+    libusb_device** device_list = nullptr;
+    ssize_t device_count = libusb_get_device_list(ctx, &device_list);
+    if (device_count < 0) {
+        errx(1, "libusb_get_device_list failed");
+    }
+
+    const char* expected_serial = getenv("ANDROID_SERIAL");
+    bool found = false;
+
+    for (ssize_t i = 0; i < device_count; ++i) {
+        libusb_device* device = device_list[i];
+        if (!is_adb_device(device)) {
+            continue;
+        }
+
+        libusb_device_handle* device_handle = nullptr;
+        int rc = libusb_open(device, &device_handle);
+        if (rc != 0) {
+            fprintf(stderr, "failed to open device %u:%u: %s\n", libusb_get_bus_number(device),
+                    libusb_get_port_number(device), libusb_error_name(rc));
+            continue;
+        }
+
+        libusb_device_descriptor device_desc;
+        libusb_get_device_descriptor(device, &device_desc);
+
+        std::optional<std::string> serial =
+                get_string_descriptor(device_handle, device_desc.iSerialNumber);
+        if (!serial) {
+            errx(1, "failed to get serial for device %u:%u", libusb_get_bus_number(device),
+                 libusb_get_port_number(device));
+        }
+
+        if (expected_serial && *serial != expected_serial) {
+            fprintf(stderr, "skipping %s (wanted %s)\n", serial->c_str(), expected_serial);
+            continue;
+        }
+
+        // Check for MS OS Descriptor v1.
+        // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeusb/c2f351f9-84d2-4a1b-9fe3-a6ca195f84d0
+        fprintf(stderr, "fetching v1 OS descriptor from device %s\n", serial->c_str());
+        check_ms_os_desc_v1(device_handle, *serial);
+        fprintf(stderr, "found v1 OS descriptor for device %s\n", serial->c_str());
+
+        // Read BOS for MS OS Descriptor 2.0 descriptors:
+        // http://download.microsoft.com/download/3/5/6/3563ED4A-F318-4B66-A181-AB1D8F6FD42D/MS_OS_2_0_desc.docx
+        fprintf(stderr, "fetching v2 OS descriptor from device %s\n", serial->c_str());
+        check_ms_os_desc_v2(device_handle, *serial);
+
+        found = true;
+    }
+
+    if (expected_serial && !found) {
+        errx(1, "failed to find device with serial %s", expected_serial);
+    }
+    return 0;
+}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 841865a..9dd6ec6 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -49,13 +49,13 @@
 #include "adb_io.h"
 #include "adb_trace.h"
 #include "adb_utils.h"
-#include "fdevent.h"
+#include "fdevent/fdevent.h"
 #include "sysdeps/chrono.h"
 
 using android::base::ScopedLockAssertion;
 
 static void remove_transport(atransport* transport);
-static void transport_unref(atransport* transport);
+static void transport_destroy(atransport* transport);
 
 // TODO: unordered_map<TransportId, atransport*>
 static auto& transport_list = *new std::list<atransport*>();
@@ -66,6 +66,7 @@
 const char* const kFeatureShell2 = "shell_v2";
 const char* const kFeatureCmd = "cmd";
 const char* const kFeatureStat2 = "stat_v2";
+const char* const kFeatureLs2 = "ls_v2";
 const char* const kFeatureLibusb = "libusb";
 const char* const kFeaturePushSync = "push_sync";
 const char* const kFeatureApex = "apex";
@@ -73,6 +74,7 @@
 const char* const kFeatureAbb = "abb";
 const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
 const char* const kFeatureAbbExec = "abb_exec";
+const char* const kFeatureRemountShell = "remount_shell";
 
 namespace {
 
@@ -542,9 +544,7 @@
     // for the first time, even if no update occurred.
     if (tracker->update_needed) {
         tracker->update_needed = false;
-
-        std::string transports = list_transports(tracker->long_output);
-        device_tracker_send(tracker, transports);
+        device_tracker_send(tracker, list_transports(tracker->long_output));
     }
 }
 
@@ -587,13 +587,11 @@
     update_transport_status();
 
     // Notify `adb track-devices` clients.
-    std::string transports = list_transports(false);
-
     device_tracker* tracker = device_tracker_list;
     while (tracker != nullptr) {
         device_tracker* next = tracker->next;
         // This may destroy the tracker if the connection is closed.
-        device_tracker_send(tracker, transports);
+        device_tracker_send(tracker, list_transports(tracker->long_output));
         tracker = next;
     }
 }
@@ -679,7 +677,6 @@
     if (t->GetConnectionState() != kCsNoPerm) {
         // The connection gets a reference to the atransport. It will release it
         // upon a read/write error.
-        t->ref_count++;
         t->connection()->SetTransportName(t->serial_name());
         t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
             if (!check_header(p.get(), t)) {
@@ -698,7 +695,7 @@
             LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
             fdevent_run_on_main_thread([t]() {
                 handle_offline(t);
-                transport_unref(t);
+                transport_destroy(t);
             });
         });
 
@@ -774,36 +771,27 @@
     }
 }
 
-static void transport_unref(atransport* t) {
+static void transport_destroy(atransport* t) {
     check_main_thread();
     CHECK(t != nullptr);
 
     std::lock_guard<std::recursive_mutex> lock(transport_lock);
-    CHECK_GT(t->ref_count, 0u);
-    t->ref_count--;
-    if (t->ref_count == 0) {
-        LOG(INFO) << "destroying transport " << t->serial_name();
-        t->connection()->Stop();
+    LOG(INFO) << "destroying transport " << t->serial_name();
+    t->connection()->Stop();
 #if ADB_HOST
-        if (t->IsTcpDevice() && !t->kicked()) {
-            D("transport: %s unref (attempting reconnection)", t->serial.c_str());
+    if (t->IsTcpDevice() && !t->kicked()) {
+        D("transport: %s destroy (attempting reconnection)", t->serial.c_str());
 
-            // We need to clear the transport's keys, so that on the next connection, it tries
-            // again from the beginning.
-            t->ResetKeys();
-            reconnect_handler.TrackTransport(t);
-        } else {
-            D("transport: %s unref (kicking and closing)", t->serial.c_str());
-            remove_transport(t);
-        }
-#else
-        D("transport: %s unref (kicking and closing)", t->serial.c_str());
-        remove_transport(t);
+        // We need to clear the transport's keys, so that on the next connection, it tries
+        // again from the beginning.
+        t->ResetKeys();
+        reconnect_handler.TrackTransport(t);
+        return;
+    }
 #endif
 
-    } else {
-        D("transport: %s unref (count=%zu)", t->serial.c_str(), t->ref_count);
-    }
+    D("transport: %s destroy (kicking and closing)", t->serial.c_str());
+    remove_transport(t);
 }
 
 static int qual_match(const std::string& to_test, const char* prefix, const std::string& qual,
@@ -1048,11 +1036,13 @@
             kFeatureShell2,
             kFeatureCmd,
             kFeatureStat2,
+            kFeatureLs2,
             kFeatureFixedPushMkdir,
             kFeatureApex,
             kFeatureAbb,
             kFeatureFixedPushSymlinkTimestamp,
             kFeatureAbbExec,
+            kFeatureRemountShell,
             // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
             // to know about. Otherwise, the client can be stuck running an old
             // version of the server even after upgrading their copy of adb.
diff --git a/adb/transport.h b/adb/transport.h
index 3473ca2..5a750ee 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -38,6 +38,7 @@
 
 #include "adb.h"
 #include "adb_unique_fd.h"
+#include "types.h"
 #include "usb.h"
 
 typedef std::unordered_set<std::string> FeatureSet;
@@ -57,6 +58,7 @@
 // The 'cmd' command is available
 extern const char* const kFeatureCmd;
 extern const char* const kFeatureStat2;
+extern const char* const kFeatureLs2;
 // The server is running with libusb enabled.
 extern const char* const kFeatureLibusb;
 // adbd supports `push --sync`.
@@ -65,10 +67,13 @@
 extern const char* const kFeatureApex;
 // adbd has b/110953234 fixed.
 extern const char* const kFeatureFixedPushMkdir;
-// adbd supports android binder bridge (abb).
+// adbd supports android binder bridge (abb) in interactive mode using shell protocol.
 extern const char* const kFeatureAbb;
+// adbd supports abb using raw pipe.
+extern const char* const kFeatureAbbExec;
 // adbd properly updates symlink timestamps on push.
 extern const char* const kFeatureFixedPushSymlinkTimestamp;
+extern const char* const kFeatureRemountShell;
 
 TransportId NextTransportId();
 
@@ -219,7 +224,7 @@
     Abort,
 };
 
-class atransport {
+class atransport : public enable_weak_from_this<atransport> {
   public:
     // TODO(danalbert): We expose waaaaaaay too much stuff because this was
     // historically just a struct, but making the whole thing a more idiomatic
@@ -242,7 +247,7 @@
     }
     atransport(ConnectionState state = kCsOffline)
         : atransport([](atransport*) { return ReconnectResult::Abort; }, state) {}
-    virtual ~atransport();
+    ~atransport();
 
     int Write(apacket* p);
     void Reset();
@@ -263,7 +268,7 @@
     usb_handle* GetUsbHandle() { return usb_handle_; }
 
     const TransportId id;
-    size_t ref_count = 0;
+
     bool online = false;
     TransportType type = kTransportAny;
 
@@ -274,8 +279,11 @@
     std::string device;
     std::string devpath;
 
+#if !ADB_HOST
     // Used to provide the key to the framework.
     std::string auth_key;
+    uint64_t auth_id;
+#endif
 
     bool IsTcpDevice() const { return type == kTransportLocal; }
 
@@ -417,11 +425,12 @@
 asocket* create_device_tracker(bool long_output);
 
 #if !ADB_HOST
-unique_fd tcp_listen_inaddr_any(int port, std::string* error);
-void server_socket_thread(std::function<unique_fd(int, std::string*)> listen_func, int port);
+unique_fd adb_listen(std::string_view addr, std::string* error);
+void server_socket_thread(std::function<unique_fd(std::string_view, std::string*)> listen_func,
+                          std::string_view addr);
 
 #if defined(__ANDROID__)
-void qemu_socket_thread(int port);
+void qemu_socket_thread(std::string_view addr);
 bool use_qemu_goldfish();
 #endif
 
diff --git a/adb/transport_fd.cpp b/adb/transport_fd.cpp
index a93e68a..8d2ad66 100644
--- a/adb/transport_fd.cpp
+++ b/adb/transport_fd.cpp
@@ -93,8 +93,8 @@
 
                 if (pfds[0].revents & POLLIN) {
                     // TODO: Should we be getting blocks from a free list?
-                    auto block = std::make_unique<IOVector::block_type>(MAX_PAYLOAD);
-                    rc = adb_read(fd_.get(), &(*block)[0], block->size());
+                    auto block = IOVector::block_type(MAX_PAYLOAD);
+                    rc = adb_read(fd_.get(), &block[0], block.size());
                     if (rc == -1) {
                         *error = std::string("read failed: ") + strerror(errno);
                         return;
@@ -102,7 +102,7 @@
                         *error = "read failed: EOF";
                         return;
                     }
-                    block->resize(rc);
+                    block.resize(rc);
                     read_buffer_.append(std::move(block));
 
                     if (!read_header_ && read_buffer_.size() >= sizeof(amessage)) {
@@ -116,7 +116,7 @@
                         auto data_chain = read_buffer_.take_front(read_header_->data_length);
 
                         // TODO: Make apacket carry around a IOVector instead of coalescing.
-                        auto payload = data_chain.coalesce<apacket::payload_type>();
+                        auto payload = std::move(data_chain).coalesce();
                         auto packet = std::make_unique<apacket>();
                         packet->msg = *read_header_;
                         packet->payload = std::move(payload);
@@ -184,8 +184,7 @@
             return WriteResult::Error;
         }
 
-        // TODO: Implement a more efficient drop_front?
-        write_buffer_.take_front(rc);
+        write_buffer_.drop_front(rc);
         writable_ = write_buffer_.empty();
         if (write_buffer_.empty()) {
             return WriteResult::Completed;
@@ -199,10 +198,10 @@
         std::lock_guard<std::mutex> lock(write_mutex_);
         const char* header_begin = reinterpret_cast<const char*>(&packet->msg);
         const char* header_end = header_begin + sizeof(packet->msg);
-        auto header_block = std::make_unique<IOVector::block_type>(header_begin, header_end);
+        auto header_block = IOVector::block_type(header_begin, header_end);
         write_buffer_.append(std::move(header_block));
         if (!packet->payload.empty()) {
-            write_buffer_.append(std::make_unique<IOVector::block_type>(std::move(packet->payload)));
+            write_buffer_.append(std::move(packet->payload));
         }
 
         WriteResult result = DispatchWrites();
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index b9f738d..c726186 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -85,22 +85,6 @@
     return local_connect_arbitrary_ports(port - 1, port, &dummy) == 0;
 }
 
-std::tuple<unique_fd, int, std::string> tcp_connect(const std::string& address,
-                                                    std::string* response) {
-    unique_fd fd;
-    int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
-    std::string serial;
-    std::string prefix_addr = address.starts_with("vsock:") ? address : "tcp:" + address;
-    if (socket_spec_connect(&fd, prefix_addr, &port, &serial, response)) {
-        close_on_exec(fd);
-        if (!set_tcp_keepalive(fd, 1)) {
-            D("warning: failed to configure TCP keepalives (%s)", strerror(errno));
-        }
-        return std::make_tuple(std::move(fd), port, serial);
-    }
-    return std::make_tuple(unique_fd(), 0, serial);
-}
-
 void connect_device(const std::string& address, std::string* response) {
     if (address.empty()) {
         *response = "empty address";
@@ -110,17 +94,25 @@
     D("connection requested to '%s'", address.c_str());
     unique_fd fd;
     int port;
-    std::string serial;
-    std::tie(fd, port, serial) = tcp_connect(address, response);
+    std::string serial, prefix_addr;
+
+    // If address does not match any socket type, it should default to TCP.
+    if (address.starts_with("vsock:") || address.starts_with("localfilesystem:")) {
+        prefix_addr = address;
+    } else {
+        prefix_addr = "tcp:" + address;
+    }
+
+    socket_spec_connect(&fd, prefix_addr, &port, &serial, response);
     if (fd.get() == -1) {
         return;
     }
-    auto reconnect = [address](atransport* t) {
+    auto reconnect = [prefix_addr](atransport* t) {
         std::string response;
         unique_fd fd;
         int port;
         std::string serial;
-        std::tie(fd, port, serial) = tcp_connect(address, &response);
+        socket_spec_connect(&fd, prefix_addr, &port, &serial, &response);
         if (fd == -1) {
             D("reconnect failed: %s", response.c_str());
             return ReconnectResult::Retry;
@@ -203,7 +195,7 @@
 std::mutex &retry_ports_lock = *new std::mutex;
 std::condition_variable &retry_ports_cond = *new std::condition_variable;
 
-static void client_socket_thread(int) {
+static void client_socket_thread(std::string_view) {
     adb_thread_setname("client_socket_thread");
     D("transport: client_socket_thread() starting");
     PollAllLocalPortsForEmulator();
@@ -248,7 +240,8 @@
 
 #else  // !ADB_HOST
 
-void server_socket_thread(std::function<unique_fd(int, std::string*)> listen_func, int port) {
+void server_socket_thread(std::function<unique_fd(std::string_view, std::string*)> listen_func,
+                          std::string_view addr) {
     adb_thread_setname("server socket");
 
     unique_fd serverfd;
@@ -256,7 +249,7 @@
 
     while (serverfd == -1) {
         errno = 0;
-        serverfd = listen_func(port, &error);
+        serverfd = listen_func(addr, &error);
         if (errno == EAFNOSUPPORT || errno == EINVAL || errno == EPROTONOSUPPORT) {
             D("unrecoverable error: '%s'", error.c_str());
             return;
@@ -276,7 +269,9 @@
             close_on_exec(fd.get());
             disable_tcp_nagle(fd.get());
             std::string serial = android::base::StringPrintf("host-%d", fd.get());
-            register_socket_transport(std::move(fd), std::move(serial), port, 1,
+            // We don't care about port value in "register_socket_transport" as it is used
+            // only from ADB_HOST. "server_socket_thread" is never called from ADB_HOST.
+            register_socket_transport(std::move(fd), std::move(serial), 0, 1,
                                       [](atransport*) { return ReconnectResult::Abort; });
         }
     }
@@ -285,38 +280,30 @@
 
 #endif
 
-unique_fd tcp_listen_inaddr_any(int port, std::string* error) {
-    return unique_fd{network_inaddr_any_server(port, SOCK_STREAM, error)};
-}
-
 #if !ADB_HOST
-static unique_fd vsock_listen(int port, std::string* error) {
-    return unique_fd{
-        socket_spec_listen(android::base::StringPrintf("vsock:%d", port), error, nullptr)
-    };
+unique_fd adb_listen(std::string_view addr, std::string* error) {
+    return unique_fd{socket_spec_listen(addr, error, nullptr)};
 }
 #endif
 
-void local_init(int port) {
+void local_init(const std::string& addr) {
 #if ADB_HOST
     D("transport: local client init");
-    std::thread(client_socket_thread, port).detach();
+    std::thread(client_socket_thread, addr).detach();
     adb_local_transport_max_port_env_override();
 #elif !defined(__ANDROID__)
     // Host adbd.
     D("transport: local server init");
-    std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
-    std::thread(server_socket_thread, vsock_listen, port).detach();
+    std::thread(server_socket_thread, adb_listen, addr).detach();
 #else
     D("transport: local server init");
     // For the adbd daemon in the system image we need to distinguish
     // between the device, and the emulator.
-    if (use_qemu_goldfish()) {
-        std::thread(qemu_socket_thread, port).detach();
+    if (addr.starts_with("tcp:") && use_qemu_goldfish()) {
+        std::thread(qemu_socket_thread, addr).detach();
     } else {
-        std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
+        std::thread(server_socket_thread, adb_listen, addr).detach();
     }
-    std::thread(server_socket_thread, vsock_listen, port).detach();
 #endif // !ADB_HOST
 }
 
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
index b66f8fa..00beb3a 100644
--- a/adb/transport_test.cpp
+++ b/adb/transport_test.cpp
@@ -19,7 +19,7 @@
 #include <gtest/gtest.h>
 
 #include "adb.h"
-#include "fdevent_test.h"
+#include "fdevent/fdevent_test.h"
 
 struct TransportTest : public FdeventTest {};
 
diff --git a/adb/types.cpp b/adb/types.cpp
new file mode 100644
index 0000000..26b77ab
--- /dev/null
+++ b/adb/types.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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 "types.h"
+
+IOVector& IOVector::operator=(IOVector&& move) noexcept {
+    chain_ = std::move(move.chain_);
+    chain_length_ = move.chain_length_;
+    begin_offset_ = move.begin_offset_;
+    start_index_ = move.start_index_;
+
+    move.clear();
+    return *this;
+}
+
+IOVector::block_type IOVector::clear() {
+    chain_length_ = 0;
+    begin_offset_ = 0;
+    start_index_ = 0;
+    block_type res;
+    if (!chain_.empty()) {
+        res = std::move(chain_.back());
+    }
+    chain_.clear();
+    return res;
+}
+
+void IOVector::drop_front(IOVector::size_type len) {
+    if (len == 0) {
+        return;
+    }
+    if (len == size()) {
+        clear();
+        return;
+    }
+    CHECK_LT(len, size());
+
+    auto dropped = 0u;
+    while (dropped < len) {
+        const auto next = chain_[start_index_].size() - begin_offset_;
+        if (dropped + next < len) {
+            pop_front_block();
+            dropped += next;
+        } else {
+            const auto taken = len - dropped;
+            begin_offset_ += taken;
+            break;
+        }
+    }
+}
+
+IOVector IOVector::take_front(IOVector::size_type len) {
+    if (len == 0) {
+        return {};
+    }
+    if (len == size()) {
+        return std::move(*this);
+    }
+
+    CHECK_GE(size(), len);
+    IOVector res;
+    // first iterate over the blocks that completely go into the other vector
+    while (chain_[start_index_].size() - begin_offset_ <= len) {
+        chain_length_ -= chain_[start_index_].size();
+        len -= chain_[start_index_].size() - begin_offset_;
+        if (chain_[start_index_].size() > begin_offset_) {
+            res.append(std::move(chain_[start_index_]));
+            if (begin_offset_) {
+                res.begin_offset_ = std::exchange(begin_offset_, 0);
+            }
+        } else {
+            begin_offset_ = 0;
+        }
+        ++start_index_;
+    }
+
+    if (len > 0) {
+        // what's left is a single buffer that needs to be split between the |res| and |this|
+        // we know that it has to be split - there was a check for the case when it has to
+        // go away as a whole.
+        if (begin_offset_ != 0 || len < chain_[start_index_].size() / 2) {
+            // let's memcpy the data out
+            block_type block(chain_[start_index_].begin() + begin_offset_,
+                             chain_[start_index_].begin() + begin_offset_ + len);
+            res.append(std::move(block));
+            begin_offset_ += len;
+        } else {
+            CHECK_EQ(begin_offset_, 0u);
+            // move out the internal buffer out and copy only the tail of it back in
+            block_type block(chain_[start_index_].begin() + len, chain_[start_index_].end());
+            chain_length_ -= chain_[start_index_].size();
+            chain_[start_index_].resize(len);
+            res.append(std::move(chain_[start_index_]));
+            chain_length_ += block.size();
+            chain_[start_index_] = std::move(block);
+        }
+    }
+    return res;
+}
+
+void IOVector::trim_front() {
+    if ((begin_offset_ == 0 && start_index_ == 0) || chain_.empty()) {
+        return;
+    }
+    block_type& first_block = chain_[start_index_];
+    if (begin_offset_ == first_block.size()) {
+        ++start_index_;
+    } else {
+        memmove(first_block.data(), first_block.data() + begin_offset_,
+                first_block.size() - begin_offset_);
+        first_block.resize(first_block.size() - begin_offset_);
+    }
+    chain_length_ -= begin_offset_;
+    begin_offset_ = 0;
+    trim_chain_front();
+}
+
+void IOVector::trim_chain_front() {
+    if (start_index_) {
+        chain_.erase(chain_.begin(), chain_.begin() + start_index_);
+        start_index_ = 0;
+    }
+}
+
+void IOVector::pop_front_block() {
+    chain_length_ -= chain_[start_index_].size();
+    begin_offset_ = 0;
+    chain_[start_index_].clear();
+    ++start_index_;
+    if (start_index_ > std::max<size_t>(4, chain_.size() / 2)) {
+        trim_chain_front();
+    }
+}
+
+IOVector::block_type IOVector::coalesce() && {
+    // Destructive coalesce() may optimize for several cases when it doesn't need to allocate
+    // new buffer, or even return one of the existing blocks as is. The only guarantee is that
+    // after this call the IOVector is in some valid state. Nothing is guaranteed about the
+    // specifics.
+    if (size() == 0) {
+        return {};
+    }
+    if (begin_offset_ == chain_[start_index_].size() && chain_.size() == start_index_ + 2) {
+        chain_length_ -= chain_.back().size();
+        auto res = std::move(chain_.back());
+        chain_.pop_back();
+        return res;
+    }
+    if (chain_.size() == start_index_ + 1) {
+        chain_length_ -= chain_.back().size();
+        auto res = std::move(chain_.back());
+        chain_.pop_back();
+        if (begin_offset_ != 0) {
+            memmove(res.data(), res.data() + begin_offset_, res.size() - begin_offset_);
+            res.resize(res.size() - begin_offset_);
+            begin_offset_ = 0;
+        }
+        return res;
+    }
+    if (auto& firstBuffer = chain_[start_index_]; firstBuffer.capacity() >= size()) {
+        auto res = std::move(chain_[start_index_]);
+        auto size = res.size();
+        chain_length_ -= size;
+        if (begin_offset_ != 0) {
+            memmove(res.data(), res.data() + begin_offset_, res.size() - begin_offset_);
+            size -= begin_offset_;
+            begin_offset_ = 0;
+        }
+        for (auto i = start_index_ + 1; i < chain_.size(); ++i) {
+            memcpy(res.data() + size, chain_[i].data(), chain_[i].size());
+            size += chain_[i].size();
+        }
+        res.resize(size);
+        ++start_index_;
+        return res;
+    }
+    return const_cast<const IOVector*>(this)->coalesce<>();
+}
+
+std::vector<adb_iovec> IOVector::iovecs() const {
+    std::vector<adb_iovec> result;
+    result.reserve(chain_.size() - start_index_);
+    iterate_blocks([&result](const char* data, size_t len) {
+        adb_iovec iov;
+        iov.iov_base = const_cast<char*>(data);
+        iov.iov_len = len;
+        result.emplace_back(iov);
+    });
+
+    return result;
+}
diff --git a/adb/types.h b/adb/types.h
index cd1366d..c619fff 100644
--- a/adb/types.h
+++ b/adb/types.h
@@ -16,22 +16,23 @@
 
 #pragma once
 
+#include <string.h>
+
 #include <algorithm>
-#include <deque>
 #include <memory>
-#include <type_traits>
 #include <utility>
 #include <vector>
 
 #include <android-base/logging.h>
 
+#include "fdevent/fdevent.h"
 #include "sysdeps/uio.h"
 
 // Essentially std::vector<char>, except without zero initialization or reallocation.
 struct Block {
     using iterator = char*;
 
-    Block() {}
+    Block() = default;
 
     explicit Block(size_t size) { allocate(size); }
 
@@ -41,24 +42,21 @@
     }
 
     Block(const Block& copy) = delete;
-    Block(Block&& move) noexcept {
-        std::swap(data_, move.data_);
-        std::swap(capacity_, move.capacity_);
-        std::swap(size_, move.size_);
-    }
+    Block(Block&& move) noexcept
+        : data_(std::exchange(move.data_, nullptr)),
+          capacity_(std::exchange(move.capacity_, 0)),
+          size_(std::exchange(move.size_, 0)) {}
 
     Block& operator=(const Block& copy) = delete;
     Block& operator=(Block&& move) noexcept {
         clear();
-
-        std::swap(data_, move.data_);
-        std::swap(capacity_, move.capacity_);
-        std::swap(size_, move.size_);
-
+        data_ = std::exchange(move.data_, nullptr);
+        capacity_ = std::exchange(move.capacity_, 0);
+        size_ = std::exchange(move.size_, 0);
         return *this;
     }
 
-    ~Block() { clear(); }
+    ~Block() = default;
 
     void resize(size_t new_size) {
         if (!data_) {
@@ -142,146 +140,63 @@
     using block_type = Block;
     using size_type = size_t;
 
-    IOVector() {}
+    IOVector() = default;
 
-    explicit IOVector(std::unique_ptr<block_type> block) {
-        append(std::move(block));
-    }
+    explicit IOVector(block_type&& block) { append(std::move(block)); }
 
     IOVector(const IOVector& copy) = delete;
     IOVector(IOVector&& move) noexcept : IOVector() { *this = std::move(move); }
 
     IOVector& operator=(const IOVector& copy) = delete;
-    IOVector& operator=(IOVector&& move) noexcept {
-        chain_ = std::move(move.chain_);
-        chain_length_ = move.chain_length_;
-        begin_offset_ = move.begin_offset_;
-        end_offset_ = move.end_offset_;
+    IOVector& operator=(IOVector&& move) noexcept;
 
-        move.chain_.clear();
-        move.chain_length_ = 0;
-        move.begin_offset_ = 0;
-        move.end_offset_ = 0;
-
-        return *this;
-    }
-
-    size_type size() const { return chain_length_ - begin_offset_ - end_offset_; }
+    size_type size() const { return chain_length_ - begin_offset_; }
     bool empty() const { return size() == 0; }
 
-    void clear() {
-        chain_length_ = 0;
-        begin_offset_ = 0;
-        end_offset_ = 0;
-        chain_.clear();
-    }
+    // Return the last block so the caller can still reuse its allocated capacity
+    // or it can be simply ignored.
+    block_type clear();
+
+    void drop_front(size_type len);
 
     // Split the first |len| bytes out of this chain into its own.
-    IOVector take_front(size_type len) {
-        IOVector head;
-
-        if (len == 0) {
-            return head;
-        }
-        CHECK_GE(size(), len);
-
-        std::shared_ptr<const block_type> first_block = chain_.front();
-        CHECK_GE(first_block->size(), begin_offset_);
-        head.append_shared(std::move(first_block));
-        head.begin_offset_ = begin_offset_;
-
-        while (head.size() < len) {
-            pop_front_block();
-            CHECK(!chain_.empty());
-
-            head.append_shared(chain_.front());
-        }
-
-        if (head.size() == len) {
-            // Head takes full ownership of the last block it took.
-            head.end_offset_ = 0;
-            begin_offset_ = 0;
-            pop_front_block();
-        } else {
-            // Head takes partial ownership of the last block it took.
-            size_t bytes_taken = head.size() - len;
-            head.end_offset_ = bytes_taken;
-            CHECK_GE(chain_.front()->size(), bytes_taken);
-            begin_offset_ = chain_.front()->size() - bytes_taken;
-        }
-
-        return head;
-    }
+    IOVector take_front(size_type len);
 
     // Add a nonempty block to the chain.
-    // The end of the chain must be a complete block (i.e. end_offset_ == 0).
-    void append(std::unique_ptr<const block_type> block) {
-        if (block->size() == 0) {
+    void append(block_type&& block) {
+        if (block.size() == 0) {
             return;
         }
-
-        CHECK_EQ(0ULL, end_offset_);
-        chain_length_ += block->size();
+        CHECK_NE(0ULL, block.size());
+        chain_length_ += block.size();
         chain_.emplace_back(std::move(block));
     }
 
-    void append(block_type&& block) { append(std::make_unique<block_type>(std::move(block))); }
-
-    void trim_front() {
-        if (begin_offset_ == 0) {
-            return;
-        }
-
-        const block_type* first_block = chain_.front().get();
-        auto copy = std::make_unique<block_type>(first_block->size() - begin_offset_);
-        memcpy(copy->data(), first_block->data() + begin_offset_, copy->size());
-        chain_.front() = std::move(copy);
-
-        chain_length_ -= begin_offset_;
-        begin_offset_ = 0;
-    }
+    void trim_front();
 
   private:
-    // append, except takes a shared_ptr.
-    // Private to prevent exterior mutation of blocks.
-    void append_shared(std::shared_ptr<const block_type> block) {
-        CHECK_NE(0ULL, block->size());
-        CHECK_EQ(0ULL, end_offset_);
-        chain_length_ += block->size();
-        chain_.emplace_back(std::move(block));
-    }
+    void trim_chain_front();
 
     // Drop the front block from the chain, and update chain_length_ appropriately.
-    void pop_front_block() {
-        chain_length_ -= chain_.front()->size();
-        begin_offset_ = 0;
-        chain_.pop_front();
-    }
+    void pop_front_block();
 
     // Iterate over the blocks with a callback with an operator()(const char*, size_t).
     template <typename Fn>
     void iterate_blocks(Fn&& callback) const {
-        if (chain_.size() == 0) {
+        if (size() == 0) {
             return;
         }
 
-        for (size_t i = 0; i < chain_.size(); ++i) {
-            const std::shared_ptr<const block_type>& block = chain_.at(i);
-            const char* begin = block->data();
-            size_t length = block->size();
+        for (size_t i = start_index_; i < chain_.size(); ++i) {
+            const auto& block = chain_[i];
+            const char* begin = block.data();
+            size_t length = block.size();
 
-            // Note that both of these conditions can be true if there's only one block.
-            if (i == 0) {
-                CHECK_GE(block->size(), begin_offset_);
+            if (i == start_index_) {
+                CHECK_GE(block.size(), begin_offset_);
                 begin += begin_offset_;
                 length -= begin_offset_;
             }
-
-            if (i == chain_.size() - 1) {
-                CHECK_GE(length, end_offset_);
-                length -= end_offset_;
-            }
-
             callback(begin, length);
         }
     }
@@ -289,7 +204,7 @@
   public:
     // Copy all of the blocks into a single block.
     template <typename CollectionType = block_type>
-    CollectionType coalesce() const {
+    CollectionType coalesce() const& {
         CollectionType result;
         if (size() == 0) {
             return result;
@@ -306,12 +221,13 @@
         return result;
     }
 
+    block_type coalesce() &&;
+
     template <typename FunctionType>
-    auto coalesced(FunctionType&& f) const ->
-        typename std::result_of<FunctionType(const char*, size_t)>::type {
-        if (chain_.size() == 1) {
+    auto coalesced(FunctionType&& f) const {
+        if (chain_.size() == start_index_ + 1) {
             // If we only have one block, we can use it directly.
-            return f(chain_.front()->data() + begin_offset_, size());
+            return f(chain_[start_index_].data() + begin_offset_, size());
         } else {
             // Otherwise, copy to a single block.
             auto data = coalesce();
@@ -320,23 +236,107 @@
     }
 
     // Get a list of iovecs that can be used to write out all of the blocks.
-    std::vector<adb_iovec> iovecs() const {
-        std::vector<adb_iovec> result;
-        iterate_blocks([&result](const char* data, size_t len) {
-            adb_iovec iov;
-            iov.iov_base = const_cast<char*>(data);
-            iov.iov_len = len;
-            result.emplace_back(iov);
-        });
-
-        return result;
-    }
+    std::vector<adb_iovec> iovecs() const;
 
   private:
     // Total length of all of the blocks in the chain.
     size_t chain_length_ = 0;
 
     size_t begin_offset_ = 0;
-    size_t end_offset_ = 0;
-    std::deque<std::shared_ptr<const block_type>> chain_;
+    size_t start_index_ = 0;
+    std::vector<block_type> chain_;
+};
+
+// An implementation of weak pointers tied to the fdevent run loop.
+//
+// This allows for code to submit a request for an object, and upon receiving
+// a response, know whether the object is still alive, or has been destroyed
+// because of other reasons. We keep a list of living weak_ptrs in each object,
+// and clear the weak_ptrs when the object is destroyed. This is safe, because
+// we require that both the destructor of the referent and the get method on
+// the weak_ptr are executed on the main thread.
+template <typename T>
+struct enable_weak_from_this;
+
+template <typename T>
+struct weak_ptr {
+    weak_ptr() = default;
+    explicit weak_ptr(T* ptr) { reset(ptr); }
+    weak_ptr(const weak_ptr& copy) { reset(copy.get()); }
+
+    weak_ptr(weak_ptr&& move) {
+        reset(move.get());
+        move.reset();
+    }
+
+    ~weak_ptr() { reset(); }
+
+    weak_ptr& operator=(const weak_ptr& copy) {
+        if (&copy == this) {
+            return *this;
+        }
+
+        reset(copy.get());
+        return *this;
+    }
+
+    weak_ptr& operator=(weak_ptr&& move) {
+        if (&move == this) {
+            return *this;
+        }
+
+        reset(move.get());
+        move.reset();
+        return *this;
+    }
+
+    T* get() {
+        check_main_thread();
+        return ptr_;
+    }
+
+    void reset(T* ptr = nullptr) {
+        check_main_thread();
+
+        if (ptr == ptr_) {
+            return;
+        }
+
+        if (ptr_) {
+            ptr_->weak_ptrs_.erase(
+                    std::remove(ptr_->weak_ptrs_.begin(), ptr_->weak_ptrs_.end(), this));
+        }
+
+        ptr_ = ptr;
+        if (ptr_) {
+            ptr_->weak_ptrs_.push_back(this);
+        }
+    }
+
+  private:
+    friend struct enable_weak_from_this<T>;
+    T* ptr_ = nullptr;
+};
+
+template <typename T>
+struct enable_weak_from_this {
+    ~enable_weak_from_this() {
+        if (!weak_ptrs_.empty()) {
+            check_main_thread();
+            for (auto& weak : weak_ptrs_) {
+                weak->ptr_ = nullptr;
+            }
+            weak_ptrs_.clear();
+        }
+    }
+
+    weak_ptr<T> weak() { return weak_ptr<T>(static_cast<T*>(this)); }
+
+    void schedule_deletion() {
+        fdevent_run_on_main_thread([this]() { delete this; });
+    }
+
+  private:
+    friend struct weak_ptr<T>;
+    std::vector<weak_ptr<T>*> weak_ptrs_;
 };
diff --git a/adb/types_test.cpp b/adb/types_test.cpp
index 1fbd2ca..2c99f95 100644
--- a/adb/types_test.cpp
+++ b/adb/types_test.cpp
@@ -19,21 +19,21 @@
 #include <memory>
 #include "types.h"
 
-static std::unique_ptr<IOVector::block_type> create_block(const std::string& string) {
-    return std::make_unique<IOVector::block_type>(string.begin(), string.end());
+static IOVector::block_type create_block(const std::string& string) {
+    return IOVector::block_type(string.begin(), string.end());
 }
 
-static std::unique_ptr<IOVector::block_type> create_block(char value, size_t len) {
-    auto block = std::make_unique<IOVector::block_type>();
-    block->resize(len);
-    memset(&(*block)[0], value, len);
+static IOVector::block_type create_block(char value, size_t len) {
+    auto block = IOVector::block_type();
+    block.resize(len);
+    memset(&(block)[0], value, len);
     return block;
 }
 
 template <typename T>
-static std::unique_ptr<IOVector::block_type> copy_block(T&& block) {
-    auto copy = std::make_unique<IOVector::block_type>();
-    copy->assign(block->begin(), block->end());
+static IOVector::block_type copy_block(const T& block) {
+    auto copy = IOVector::block_type();
+    copy.assign(block.begin(), block.end());
     return copy;
 }
 
@@ -50,7 +50,7 @@
     bc.append(copy_block(block));
     ASSERT_EQ(100ULL, bc.size());
     auto coalesced = bc.coalesce();
-    ASSERT_EQ(*block, coalesced);
+    ASSERT_EQ(block, coalesced);
 }
 
 TEST(IOVector, single_block_split) {
@@ -60,8 +60,8 @@
     IOVector foo = bc.take_front(3);
     ASSERT_EQ(3ULL, foo.size());
     ASSERT_EQ(3ULL, bc.size());
-    ASSERT_EQ(*create_block("foo"), foo.coalesce());
-    ASSERT_EQ(*create_block("bar"), bc.coalesce());
+    ASSERT_EQ(create_block("foo"), foo.coalesce());
+    ASSERT_EQ(create_block("bar"), bc.coalesce());
 }
 
 TEST(IOVector, aligned_split) {
@@ -73,15 +73,15 @@
 
     IOVector foo = bc.take_front(3);
     ASSERT_EQ(3ULL, foo.size());
-    ASSERT_EQ(*create_block("foo"), foo.coalesce());
+    ASSERT_EQ(create_block("foo"), foo.coalesce());
 
     IOVector bar = bc.take_front(3);
     ASSERT_EQ(3ULL, bar.size());
-    ASSERT_EQ(*create_block("bar"), bar.coalesce());
+    ASSERT_EQ(create_block("bar"), bar.coalesce());
 
     IOVector baz = bc.take_front(3);
     ASSERT_EQ(3ULL, baz.size());
-    ASSERT_EQ(*create_block("baz"), baz.coalesce());
+    ASSERT_EQ(create_block("baz"), baz.coalesce());
 
     ASSERT_EQ(0ULL, bc.size());
 }
@@ -97,23 +97,23 @@
     // Aligned left, misaligned right, across multiple blocks.
     IOVector foob = bc.take_front(4);
     ASSERT_EQ(4ULL, foob.size());
-    ASSERT_EQ(*create_block("foob"), foob.coalesce());
+    ASSERT_EQ(create_block("foob"), foob.coalesce());
 
     // Misaligned left, misaligned right, in one block.
     IOVector a = bc.take_front(1);
     ASSERT_EQ(1ULL, a.size());
-    ASSERT_EQ(*create_block("a"), a.coalesce());
+    ASSERT_EQ(create_block("a"), a.coalesce());
 
     // Misaligned left, misaligned right, across two blocks.
     IOVector rba = bc.take_front(3);
     ASSERT_EQ(3ULL, rba.size());
-    ASSERT_EQ(*create_block("rba"), rba.coalesce());
+    ASSERT_EQ(create_block("rba"), rba.coalesce());
 
     // Misaligned left, misaligned right, across three blocks.
     IOVector zquxquu = bc.take_front(7);
     ASSERT_EQ(7ULL, zquxquu.size());
-    ASSERT_EQ(*create_block("zquxquu"), zquxquu.coalesce());
+    ASSERT_EQ(create_block("zquxquu"), zquxquu.coalesce());
 
     ASSERT_EQ(1ULL, bc.size());
-    ASSERT_EQ(*create_block("x"), bc.coalesce());
+    ASSERT_EQ(create_block("x"), bc.coalesce());
 }
diff --git a/base/Android.bp b/base/Android.bp
index 38f301a..8351461 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -20,8 +20,14 @@
         "-Wall",
         "-Werror",
         "-Wextra",
-        "-D_FILE_OFFSET_BITS=64",
     ],
+    target: {
+        android: {
+            cflags: [
+                "-D_FILE_OFFSET_BITS=64",
+            ],
+        },
+    },
 }
 
 cc_library_headers {
@@ -29,6 +35,7 @@
     vendor_available: true,
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
 
     target: {
@@ -45,14 +52,16 @@
     name: "libbase_defaults",
     defaults: ["libbase_cflags_defaults"],
     srcs: [
+        "abi_compatibility.cpp",
         "chrono_utils.cpp",
         "cmsg.cpp",
         "file.cpp",
         "logging.cpp",
         "mapped_file.cpp",
+        "parsebool.cpp",
         "parsenetaddress.cpp",
+        "process.cpp",
         "properties.cpp",
-        "quick_exit.cpp",
         "stringprintf.cpp",
         "strings.cpp",
         "threads.cpp",
@@ -100,6 +109,7 @@
     vendor_available: true,
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
         support_system_process: true,
@@ -108,6 +118,9 @@
         "libbase_headers",
     ],
     export_header_lib_headers: ["libbase_headers"],
+    static_libs: ["fmtlib"],
+    whole_static_libs: ["fmtlib"],
+    export_static_lib_headers: ["fmtlib"],
 }
 
 cc_library_static {
@@ -116,6 +129,9 @@
     sdk_version: "current",
     stl: "c++_static",
     export_include_dirs: ["include"],
+    static_libs: ["fmtlib_ndk"],
+    whole_static_libs: ["fmtlib_ndk"],
+    export_static_lib_headers: ["fmtlib_ndk"],
 }
 
 // Tests
@@ -128,15 +144,19 @@
         "cmsg_test.cpp",
         "endian_test.cpp",
         "errors_test.cpp",
+        "expected_test.cpp",
         "file_test.cpp",
         "logging_test.cpp",
         "macros_test.cpp",
         "mapped_file_test.cpp",
+        "no_destructor_test.cpp",
         "parsedouble_test.cpp",
+        "parsebool_test.cpp",
         "parseint_test.cpp",
         "parsenetaddress_test.cpp",
+        "process_test.cpp",
         "properties_test.cpp",
-        "quick_exit_test.cpp",
+        "result_test.cpp",
         "scopeguard_test.cpp",
         "stringprintf_test.cpp",
         "strings_test.cpp",
@@ -171,3 +191,21 @@
     },
     test_suites: ["device-tests"],
 }
+
+cc_benchmark {
+    name: "libbase_benchmark",
+    defaults: ["libbase_cflags_defaults"],
+
+    srcs: ["format_benchmark.cpp"],
+    shared_libs: ["libbase"],
+
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+}
diff --git a/base/README.md b/base/README.md
new file mode 100644
index 0000000..2ef5c10
--- /dev/null
+++ b/base/README.md
@@ -0,0 +1,42 @@
+# libbase
+
+## Who is this library for?
+
+This library is a collection of convenience functions to make common tasks
+easier and less error-prone.
+
+In this context, "error-prone" covers both "hard to do correctly" and
+"hard to do with good performance", but as a general purpose library,
+libbase's primary focus is on making it easier to do things easily and
+correctly when a compromise has to be made between "simplest API" on the
+one hand and "fastest implementation" on the other. Though obviously
+the ideal is to have both.
+
+## Should my routine be added?
+
+The intention is to cover the 80% use cases, not be all things to all users.
+
+If you have a routine that's really useful in your project,
+congratulations. But that doesn't mean it should be here rather than
+just in your project.
+
+The question for libbase is "should everyone be doing this?"/"does this
+make everyone's code cleaner/safer?". Historically we've considered the
+bar for inclusion to be "are there at least three *unrelated* projects
+that would be cleaned up by doing so".
+
+If your routine is actually something from a future C++ standard (that
+isn't yet in libc++), or it's widely used in another library, that helps
+show that there's precedent. Being able to say "so-and-so has used this
+API for n years" is a good way to reduce concerns about API choices.
+
+## Any other restrictions?
+
+Unlike most Android code, code in libbase has to build for Mac and
+Windows too.
+
+Code here is also expected to have good test coverage.
+
+By its nature, it's difficult to change libbase API. It's often best
+to start using your routine just in your project, and let it "graduate"
+after you're certain that the API is solid.
diff --git a/base/abi_compatibility.cpp b/base/abi_compatibility.cpp
new file mode 100644
index 0000000..06a7801
--- /dev/null
+++ b/base/abi_compatibility.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 <memory>
+
+#include "android-base/cmsg.h"
+#include "android-base/file.h"
+#include "android-base/mapped_file.h"
+#include "android-base/unique_fd.h"
+
+namespace android {
+namespace base {
+
+// These ABI-compatibility shims are in a separate file for two reasons:
+//   1. If they were in the file with the actual functions, it prevents calls to
+//      those functions by other functions in the file, due to ambiguity.
+//   2. We will hopefully be able to delete these quickly.
+
+#if !defined(_WIN32)
+ssize_t SendFileDescriptorVector(int sockfd, const void* data, size_t len,
+                                 const std::vector<int>& fds) {
+  return SendFileDescriptorVector(borrowed_fd(sockfd), data, len, fds);
+}
+
+ssize_t ReceiveFileDescriptorVector(int sockfd, void* data, size_t len, size_t max_fds,
+                                    std::vector<unique_fd>* fds) {
+  return ReceiveFileDescriptorVector(borrowed_fd(sockfd), data, len, max_fds, fds);
+}
+#endif
+
+bool ReadFdToString(int fd, std::string* content) {
+  return ReadFdToString(borrowed_fd(fd), content);
+}
+
+bool WriteStringToFd(const std::string& content, int fd) {
+  return WriteStringToFd(content, borrowed_fd(fd));
+}
+
+bool ReadFully(int fd, void* data, size_t byte_count) {
+  return ReadFully(borrowed_fd(fd), data, byte_count);
+}
+
+bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset) {
+  return ReadFullyAtOffset(borrowed_fd(fd), data, byte_count, offset);
+}
+
+bool WriteFully(int fd, const void* data, size_t byte_count) {
+  return WriteFully(borrowed_fd(fd), data, byte_count);
+}
+
+#if defined(__LP64__)
+#define MAPPEDFILE_FROMFD _ZN10MappedFile6FromFdEilmi
+#else
+#define MAPPEDFILE_FROMFD _ZN10MappedFile6FromFdEixmi
+#endif
+
+#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
+extern "C" std::unique_ptr<MappedFile> MAPPEDFILE_FROMFD(int fd, off64_t offset, size_t length,
+                                                         int prot) {
+  return MappedFile::FromFd(fd, offset, length, prot);
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/base/cmsg.cpp b/base/cmsg.cpp
index 42866f8..1fa873c 100644
--- a/base/cmsg.cpp
+++ b/base/cmsg.cpp
@@ -29,7 +29,7 @@
 namespace android {
 namespace base {
 
-ssize_t SendFileDescriptorVector(int sockfd, const void* data, size_t len,
+ssize_t SendFileDescriptorVector(borrowed_fd sockfd, const void* data, size_t len,
                                  const std::vector<int>& fds) {
   size_t cmsg_space = CMSG_SPACE(sizeof(int) * fds.size());
   size_t cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
@@ -67,10 +67,10 @@
   int flags = 0;
 #endif
 
-  return TEMP_FAILURE_RETRY(sendmsg(sockfd, &msg, flags));
+  return TEMP_FAILURE_RETRY(sendmsg(sockfd.get(), &msg, flags));
 }
 
-ssize_t ReceiveFileDescriptorVector(int sockfd, void* data, size_t len, size_t max_fds,
+ssize_t ReceiveFileDescriptorVector(borrowed_fd sockfd, void* data, size_t len, size_t max_fds,
                                     std::vector<unique_fd>* fds) {
   fds->clear();
 
@@ -98,7 +98,7 @@
   flags |= MSG_CMSG_CLOEXEC | MSG_NOSIGNAL;
 #endif
 
-  ssize_t rc = TEMP_FAILURE_RETRY(recvmsg(sockfd, &msg, flags));
+  ssize_t rc = TEMP_FAILURE_RETRY(recvmsg(sockfd.get(), &msg, flags));
 
   if (rc == -1) {
     return -1;
diff --git a/base/errors_unix.cpp b/base/errors_unix.cpp
index 296995e..48269b6 100644
--- a/base/errors_unix.cpp
+++ b/base/errors_unix.cpp
@@ -17,6 +17,7 @@
 #include "android-base/errors.h"
 
 #include <errno.h>
+#include <string.h>
 
 namespace android {
 namespace base {
diff --git a/base/expected_test.cpp b/base/expected_test.cpp
new file mode 100644
index 0000000..a74bc1d
--- /dev/null
+++ b/base/expected_test.cpp
@@ -0,0 +1,894 @@
+/*
+ * 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 "android-base/expected.h"
+
+#include <cstdio>
+#include <memory>
+#include <string>
+
+#include <gtest/gtest.h>
+
+using android::base::expected;
+using android::base::unexpected;
+
+typedef expected<int, int> exp_int;
+typedef expected<double, double> exp_double;
+typedef expected<std::string, std::string> exp_string;
+typedef expected<std::pair<std::string, int>, int> exp_pair;
+typedef expected<void, int> exp_void;
+
+struct T {
+  int a;
+  int b;
+  T() = default;
+  T(int a, int b) noexcept : a(a), b(b) {}
+};
+bool operator==(const T& x, const T& y) {
+  return x.a == y.a && x.b == y.b;
+}
+bool operator!=(const T& x, const T& y) {
+  return x.a != y.a || x.b != y.b;
+}
+
+struct E {
+    std::string message;
+    int cause;
+    E(const std::string& message, int cause) : message(message), cause(cause) {}
+};
+
+typedef expected<T,E> exp_complex;
+
+TEST(Expected, testDefaultConstructible) {
+  exp_int e;
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ(0, e.value());
+
+  exp_complex e2;
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(T(0,0), e2.value());
+
+  exp_void e3;
+  EXPECT_TRUE(e3.has_value());
+}
+
+TEST(Expected, testCopyConstructible) {
+  exp_int e;
+  exp_int e2 = e;
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(0, e.value());
+  EXPECT_EQ(0, e2.value());
+
+  exp_void e3;
+  exp_void e4 = e3;
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+}
+
+TEST(Expected, testMoveConstructible) {
+  exp_int e;
+  exp_int e2 = std::move(e);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(0, e.value());
+  EXPECT_EQ(0, e2.value());
+
+  exp_string e3(std::string("hello"));
+  exp_string e4 = std::move(e3);
+
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+  EXPECT_EQ("", e3.value()); // e3 is moved
+  EXPECT_EQ("hello", e4.value());
+
+  exp_void e5;
+  exp_void e6 = std::move(e5);
+  EXPECT_TRUE(e5.has_value());
+  EXPECT_TRUE(e6.has_value());
+}
+
+TEST(Expected, testCopyConstructibleFromConvertibleType) {
+  exp_double e = 3.3f;
+  exp_int e2 = e;
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(3.3f, e.value());
+  EXPECT_EQ(3, e2.value());
+}
+
+TEST(Expected, testMoveConstructibleFromConvertibleType) {
+  exp_double e = 3.3f;
+  exp_int e2 = std::move(e);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(3.3f, e.value());
+  EXPECT_EQ(3, e2.value());
+}
+
+TEST(Expected, testConstructibleFromValue) {
+  exp_int e = 3;
+  exp_double e2 = 5.5f;
+  exp_string e3 = std::string("hello");
+  exp_complex e4 = T(10, 20);
+  exp_void e5 = {};
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+  EXPECT_TRUE(e5.has_value());
+  EXPECT_EQ(3, e.value());
+  EXPECT_EQ(5.5f, e2.value());
+  EXPECT_EQ("hello", e3.value());
+  EXPECT_EQ(T(10,20), e4.value());
+}
+
+TEST(Expected, testConstructibleFromMovedValue) {
+  std::string hello = "hello";
+  exp_string e = std::move(hello);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ("hello", e.value());
+  EXPECT_EQ("", hello);
+}
+
+TEST(Expected, testConstructibleFromConvertibleValue) {
+  exp_int e = 3.3f; // double to int
+  exp_string e2 = "hello"; // char* to std::string
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ(3, e.value());
+
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ("hello", e2.value());
+}
+
+TEST(Expected, testConstructibleFromUnexpected) {
+  exp_int::unexpected_type unexp = unexpected(10);
+  exp_int e = unexp;
+
+  exp_double::unexpected_type unexp2 = unexpected(10.5f);
+  exp_double e2 = unexp2;
+
+  exp_string::unexpected_type unexp3 = unexpected(std::string("error"));
+  exp_string e3 = unexp3;
+
+  exp_void::unexpected_type unexp4 = unexpected(10);
+  exp_void e4 = unexp4;
+
+  EXPECT_FALSE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_FALSE(e4.has_value());
+  EXPECT_EQ(10, e.error());
+  EXPECT_EQ(10.5f, e2.error());
+  EXPECT_EQ("error", e3.error());
+  EXPECT_EQ(10, e4.error());
+}
+
+TEST(Expected, testMoveConstructibleFromUnexpected) {
+  exp_int e = unexpected(10);
+  exp_double e2 = unexpected(10.5f);
+  exp_string e3 = unexpected(std::string("error"));
+  exp_void e4 = unexpected(10);
+
+  EXPECT_FALSE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_FALSE(e4.has_value());
+  EXPECT_EQ(10, e.error());
+  EXPECT_EQ(10.5f, e2.error());
+  EXPECT_EQ("error", e3.error());
+  EXPECT_EQ(10, e4.error());
+}
+
+TEST(Expected, testConstructibleByForwarding) {
+  exp_string e(std::in_place, 5, 'a');
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ("aaaaa", e.value());
+
+  exp_string e2({'a', 'b', 'c'});
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ("abc", e2.value());
+
+  exp_pair e3({"hello", 30});
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_EQ("hello",e3->first);
+  EXPECT_EQ(30,e3->second);
+
+  exp_void e4({});
+  EXPECT_TRUE(e4.has_value());
+}
+
+TEST(Expected, testDestructible) {
+  bool destroyed = false;
+  struct T {
+    bool* flag_;
+    T(bool* flag) : flag_(flag) {}
+    ~T() { *flag_ = true; }
+  };
+  {
+    expected<T, int> exp = T(&destroyed);
+  }
+  EXPECT_TRUE(destroyed);
+}
+
+TEST(Expected, testAssignable) {
+  exp_int e = 10;
+  exp_int e2 = 20;
+  e = e2;
+
+  EXPECT_EQ(20, e.value());
+  EXPECT_EQ(20, e2.value());
+
+  exp_int e3 = 10;
+  exp_int e4 = 20;
+  e3 = std::move(e4);
+
+  EXPECT_EQ(20, e3.value());
+  EXPECT_EQ(20, e4.value());
+
+  exp_void e5 = unexpected(10);
+  ASSERT_FALSE(e5.has_value());
+  exp_void e6;
+  e5 = e6;
+
+  EXPECT_TRUE(e5.has_value());
+  EXPECT_TRUE(e6.has_value());
+}
+
+TEST(Expected, testAssignableFromValue) {
+  exp_int e = 10;
+  e = 20;
+  EXPECT_EQ(20, e.value());
+
+  exp_double e2 = 3.5f;
+  e2 = 10.5f;
+  EXPECT_EQ(10.5f, e2.value());
+
+  exp_string e3 = "hello";
+  e3 = "world";
+  EXPECT_EQ("world", e3.value());
+
+  exp_void e4 = unexpected(10);
+  ASSERT_FALSE(e4.has_value());
+  e4 = {};
+  EXPECT_TRUE(e4.has_value());
+}
+
+TEST(Expected, testAssignableFromUnexpected) {
+  exp_int e = 10;
+  e = unexpected(30);
+  EXPECT_FALSE(e.has_value());
+  EXPECT_EQ(30, e.error());
+
+  exp_double e2 = 3.5f;
+  e2 = unexpected(10.5f);
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_EQ(10.5f, e2.error());
+
+  exp_string e3 = "hello";
+  e3 = unexpected("world");
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_EQ("world", e3.error());
+
+  exp_void e4 = {};
+  e4 = unexpected(10);
+  EXPECT_FALSE(e4.has_value());
+  EXPECT_EQ(10, e4.error());
+}
+
+TEST(Expected, testAssignableFromMovedValue) {
+  std::string world = "world";
+  exp_string e = "hello";
+  e = std::move(world);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_EQ("world", e.value());
+  EXPECT_EQ("", world);
+}
+
+TEST(Expected, testAssignableFromMovedUnexpected) {
+  std::string world = "world";
+  exp_string e = "hello";
+  e = unexpected(std::move(world));
+
+  EXPECT_FALSE(e.has_value());
+  EXPECT_EQ("world", e.error());
+  EXPECT_EQ("", world);
+}
+
+TEST(Expected, testEmplace) {
+  struct T {
+    int a;
+    double b;
+    T() {}
+    T(int a, double b) noexcept : a(a), b(b) {}
+  };
+  expected<T, int> exp;
+  T& t = exp.emplace(3, 10.5f);
+
+  EXPECT_TRUE(exp.has_value());
+  EXPECT_EQ(3, t.a);
+  EXPECT_EQ(10.5f, t.b);
+  EXPECT_EQ(3, exp.value().a);
+  EXPECT_EQ(10.5, exp.value().b);
+
+  exp_void e = unexpected(10);
+  ASSERT_FALSE(e.has_value());
+  e.emplace();
+  EXPECT_TRUE(e.has_value());
+}
+
+TEST(Expected, testSwapExpectedExpected) {
+  exp_int e = 10;
+  exp_int e2 = 20;
+  e.swap(e2);
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(20, e.value());
+  EXPECT_EQ(10, e2.value());
+
+  exp_void e3;
+  exp_void e4;
+  e3.swap(e4);
+
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+}
+
+TEST(Expected, testSwapUnexpectedUnexpected) {
+  exp_int e = unexpected(10);
+  exp_int e2 = unexpected(20);
+  e.swap(e2);
+  EXPECT_FALSE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_EQ(20, e.error());
+  EXPECT_EQ(10, e2.error());
+
+  exp_void e3 = unexpected(10);
+  exp_void e4 = unexpected(20);
+  e3.swap(e4);
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_FALSE(e4.has_value());
+  EXPECT_EQ(20, e3.error());
+  EXPECT_EQ(10, e4.error());
+}
+
+TEST(Expected, testSwapExpectedUnepected) {
+  exp_int e = 10;
+  exp_int e2 = unexpected(30);
+  e.swap(e2);
+  EXPECT_FALSE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(30, e.error());
+  EXPECT_EQ(10, e2.value());
+
+  exp_void e3;
+  exp_void e4 = unexpected(10);
+  e3.swap(e4);
+  EXPECT_FALSE(e3.has_value());
+  EXPECT_TRUE(e4.has_value());
+  EXPECT_EQ(10, e3.error());
+}
+
+TEST(Expected, testDereference) {
+  struct T {
+    int a;
+    double b;
+    T() {}
+    T(int a, double b) : a(a), b(b) {}
+  };
+  expected<T, int> exp = T(3, 10.5f);
+
+  EXPECT_EQ(3, exp->a);
+  EXPECT_EQ(10.5f, exp->b);
+
+  EXPECT_EQ(3, (*exp).a);
+  EXPECT_EQ(10.5f, (*exp).b);
+}
+
+TEST(Expected, testTest) {
+  exp_int e = 10;
+  EXPECT_TRUE(e);
+  EXPECT_TRUE(e.has_value());
+
+  exp_int e2 = unexpected(10);
+  EXPECT_FALSE(e2);
+  EXPECT_FALSE(e2.has_value());
+}
+
+TEST(Expected, testGetValue) {
+  exp_int e = 10;
+  EXPECT_EQ(10, e.value());
+  EXPECT_EQ(10, e.value_or(20));
+
+  exp_int e2 = unexpected(10);
+  EXPECT_EQ(10, e2.error());
+  EXPECT_EQ(20, e2.value_or(20));
+}
+
+TEST(Expected, testSameValues) {
+  exp_int e = 10;
+  exp_int e2 = 10;
+  EXPECT_TRUE(e == e2);
+  EXPECT_TRUE(e2 == e);
+  EXPECT_FALSE(e != e2);
+  EXPECT_FALSE(e2 != e);
+
+  exp_void e3;
+  exp_void e4;
+  EXPECT_TRUE(e3 == e4);
+  EXPECT_TRUE(e4 == e3);
+  EXPECT_FALSE(e3 != e4);
+  EXPECT_FALSE(e4 != e3);
+}
+
+TEST(Expected, testDifferentValues) {
+  exp_int e = 10;
+  exp_int e2 = 20;
+  EXPECT_FALSE(e == e2);
+  EXPECT_FALSE(e2 == e);
+  EXPECT_TRUE(e != e2);
+  EXPECT_TRUE(e2 != e);
+}
+
+TEST(Expected, testValueWithError) {
+  exp_int e = 10;
+  exp_int e2 = unexpected(10);
+  EXPECT_FALSE(e == e2);
+  EXPECT_FALSE(e2 == e);
+  EXPECT_TRUE(e != e2);
+  EXPECT_TRUE(e2 != e);
+
+  exp_void e3;
+  exp_void e4 = unexpected(10);
+  EXPECT_FALSE(e3 == e4);
+  EXPECT_FALSE(e4 == e3);
+  EXPECT_TRUE(e3 != e4);
+  EXPECT_TRUE(e4 != e3);
+}
+
+TEST(Expected, testSameErrors) {
+  exp_int e = unexpected(10);
+  exp_int e2 = unexpected(10);
+  EXPECT_TRUE(e == e2);
+  EXPECT_TRUE(e2 == e);
+  EXPECT_FALSE(e != e2);
+  EXPECT_FALSE(e2 != e);
+
+  exp_void e3 = unexpected(10);
+  exp_void e4 = unexpected(10);
+  EXPECT_TRUE(e3 == e4);
+  EXPECT_TRUE(e4 == e3);
+  EXPECT_FALSE(e3 != e4);
+  EXPECT_FALSE(e4 != e3);
+}
+
+TEST(Expected, testDifferentErrors) {
+  exp_int e = unexpected(10);
+  exp_int e2 = unexpected(20);
+  EXPECT_FALSE(e == e2);
+  EXPECT_FALSE(e2 == e);
+  EXPECT_TRUE(e != e2);
+  EXPECT_TRUE(e2 != e);
+
+  exp_void e3 = unexpected(10);
+  exp_void e4 = unexpected(20);
+  EXPECT_FALSE(e3 == e4);
+  EXPECT_FALSE(e4 == e3);
+  EXPECT_TRUE(e3 != e4);
+  EXPECT_TRUE(e4 != e3);
+}
+
+TEST(Expected, testCompareWithSameValue) {
+  exp_int e = 10;
+  int value = 10;
+  EXPECT_TRUE(e == value);
+  EXPECT_TRUE(value == e);
+  EXPECT_FALSE(e != value);
+  EXPECT_FALSE(value != e);
+}
+
+TEST(Expected, testCompareWithDifferentValue) {
+  exp_int e = 10;
+  int value = 20;
+  EXPECT_FALSE(e == value);
+  EXPECT_FALSE(value == e);
+  EXPECT_TRUE(e != value);
+  EXPECT_TRUE(value != e);
+}
+
+TEST(Expected, testCompareWithSameError) {
+  exp_int e = unexpected(10);
+  exp_int::unexpected_type error = 10;
+  EXPECT_TRUE(e == error);
+  EXPECT_TRUE(error == e);
+  EXPECT_FALSE(e != error);
+  EXPECT_FALSE(error != e);
+
+  exp_void e2 = unexpected(10);
+  exp_void::unexpected_type error2 = 10;
+  EXPECT_TRUE(e2 == error2);
+  EXPECT_TRUE(error2 == e2);
+  EXPECT_FALSE(e2 != error2);
+  EXPECT_FALSE(error2 != e2);
+}
+
+TEST(Expected, testCompareWithDifferentError) {
+  exp_int e = unexpected(10);
+  exp_int::unexpected_type error = 20;
+  EXPECT_FALSE(e == error);
+  EXPECT_FALSE(error == e);
+  EXPECT_TRUE(e != error);
+  EXPECT_TRUE(error != e);
+
+  exp_void e2 = unexpected(10);
+  exp_void::unexpected_type error2 = 20;
+  EXPECT_FALSE(e2 == error2);
+  EXPECT_FALSE(error2 == e2);
+  EXPECT_TRUE(e2 != error2);
+  EXPECT_TRUE(error2 != e2);
+}
+
+TEST(Expected, testCompareDifferentType) {
+  expected<int,int> e = 10;
+  expected<int32_t, int> e2 = 10;
+  EXPECT_TRUE(e == e2);
+  e2 = 20;
+  EXPECT_FALSE(e == e2);
+
+  expected<std::string_view,int> e3 = "hello";
+  expected<std::string,int> e4 = "hello";
+  EXPECT_TRUE(e3 == e4);
+  e4 = "world";
+  EXPECT_FALSE(e3 == e4);
+
+  expected<void,int> e5;
+  expected<int,int> e6 = 10;
+  EXPECT_FALSE(e5 == e6);
+  EXPECT_FALSE(e6 == e5);
+}
+
+TEST(Expected, testDivideExample) {
+  struct QR {
+    int quotient;
+    int remainder;
+    QR(int q, int r) noexcept : quotient(q), remainder(r) {}
+    bool operator==(const QR& rhs) const {
+      return quotient == rhs.quotient && remainder == rhs.remainder;
+    }
+    bool operator!=(const QR& rhs) const {
+      return quotient != rhs.quotient || remainder == rhs.remainder;
+    }
+  };
+
+  auto divide = [](int x, int y) -> expected<QR,E> {
+    if (y == 0) {
+      return unexpected(E("divide by zero", -1));
+    } else {
+      return QR(x / y, x % y);
+    }
+  };
+
+  EXPECT_FALSE(divide(10, 0));
+  EXPECT_EQ("divide by zero", divide(10, 0).error().message);
+  EXPECT_EQ(-1, divide(10, 0).error().cause);
+
+  EXPECT_TRUE(divide(10, 3));
+  EXPECT_EQ(QR(3, 1), divide(10, 3));
+}
+
+TEST(Expected, testPair) {
+  auto test = [](bool yes) -> exp_pair {
+    if (yes) {
+      return exp_pair({"yes", 42});
+    } else {
+      return unexpected(42);
+    }
+  };
+
+  auto r = test(true);
+  EXPECT_TRUE(r);
+  EXPECT_EQ("yes", r->first);
+}
+
+TEST(Expected, testVoid) {
+  auto test = [](bool ok) -> exp_void {
+    if (ok) {
+      return {};
+    } else {
+      return unexpected(10);
+    }
+  };
+
+  auto r = test(true);
+  EXPECT_TRUE(r);
+  r = test(false);
+  EXPECT_FALSE(r);
+  EXPECT_EQ(10, r.error());
+}
+
+// copied from result_test.cpp
+struct ConstructorTracker {
+  static size_t constructor_called;
+  static size_t copy_constructor_called;
+  static size_t move_constructor_called;
+  static size_t copy_assignment_called;
+  static size_t move_assignment_called;
+
+  template <typename T,
+    typename std::enable_if_t<std::is_convertible_v<T, std::string>>* = nullptr>
+  ConstructorTracker(T&& string) : string(string) {
+    ++constructor_called;
+  }
+  ConstructorTracker(const ConstructorTracker& ct) {
+    ++copy_constructor_called;
+    string = ct.string;
+  }
+  ConstructorTracker(ConstructorTracker&& ct) noexcept {
+    ++move_constructor_called;
+    string = std::move(ct.string);
+  }
+  ConstructorTracker& operator=(const ConstructorTracker& ct) {
+    ++copy_assignment_called;
+    string = ct.string;
+    return *this;
+  }
+  ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
+    ++move_assignment_called;
+    string = std::move(ct.string);
+    return *this;
+  }
+  static void Reset() {
+    constructor_called = 0;
+    copy_constructor_called = 0;
+    move_constructor_called = 0;
+    copy_assignment_called = 0;
+    move_assignment_called = 0;
+  }
+  std::string string;
+};
+
+size_t ConstructorTracker::constructor_called = 0;
+size_t ConstructorTracker::copy_constructor_called = 0;
+size_t ConstructorTracker::move_constructor_called = 0;
+size_t ConstructorTracker::copy_assignment_called = 0;
+size_t ConstructorTracker::move_assignment_called = 0;
+
+typedef expected<ConstructorTracker, int> exp_track;
+
+TEST(Expected, testNumberOfCopies) {
+  // default constructor
+  ConstructorTracker::Reset();
+  exp_track e("hello");
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // copy constructor
+  ConstructorTracker::Reset();
+  exp_track e2 = e;
+  EXPECT_EQ(0U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // move constructor
+  ConstructorTracker::Reset();
+  exp_track e3 = std::move(e);
+  EXPECT_EQ(0U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // construct from lvalue
+  ConstructorTracker::Reset();
+  ConstructorTracker ct = "hello";
+  exp_track e4(ct);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // construct from rvalue
+  ConstructorTracker::Reset();
+  ConstructorTracker ct2 = "hello";
+  exp_track e5(std::move(ct2));
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // copy assignment
+  ConstructorTracker::Reset();
+  exp_track e6 = "hello";
+  exp_track e7 = "world";
+  e7 = e6;
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  // move assignment
+  ConstructorTracker::Reset();
+  exp_track e8 = "hello";
+  exp_track e9 = "world";
+  e9 = std::move(e8);
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_assignment_called);
+
+  // swap
+  ConstructorTracker::Reset();
+  exp_track e10 = "hello";
+  exp_track e11 = "world";
+  std::swap(e10, e11);
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(2U, ConstructorTracker::move_assignment_called);
+}
+
+TEST(Expected, testNoCopyOnReturn) {
+  auto test = [](const std::string& in) -> exp_track {
+    if (in.empty()) {
+      return "literal string";
+    }
+    if (in == "test2") {
+      return ConstructorTracker(in + in + "2");
+    }
+    ConstructorTracker result(in + " " + in);
+    return result;
+  };
+
+  ConstructorTracker::Reset();
+  auto result1 = test("");
+  ASSERT_TRUE(result1);
+  EXPECT_EQ("literal string", result1->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  ConstructorTracker::Reset();
+  auto result2 = test("test2");
+  ASSERT_TRUE(result2);
+  EXPECT_EQ("test2test22", result2->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  ConstructorTracker::Reset();
+  auto result3 = test("test3");
+  ASSERT_TRUE(result3);
+  EXPECT_EQ("test3 test3", result3->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+}
+
+TEST(Expected, testNested) {
+  expected<exp_string, std::string> e = "hello";
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e.value().has_value());
+  EXPECT_TRUE(e);
+  EXPECT_TRUE(*e);
+  EXPECT_EQ("hello", e.value().value());
+
+  expected<exp_string, std::string> e2 = unexpected("world");
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_FALSE(e2);
+  EXPECT_EQ("world", e2.error());
+
+  expected<exp_string, std::string> e3 = exp_string(unexpected("world"));
+  EXPECT_TRUE(e3.has_value());
+  EXPECT_FALSE(e3.value().has_value());
+  EXPECT_TRUE(e3);
+  EXPECT_FALSE(*e3);
+  EXPECT_EQ("world", e3.value().error());
+}
+
+constexpr bool equals(const char* a, const char* b) {
+  return (a == nullptr && b == nullptr) ||
+      (a != nullptr && b != nullptr && *a == *b &&
+       (*a == '\0' || equals(a + 1, b + 1)));
+}
+
+TEST(Expected, testConstexpr) {
+  // Compliation error will occur if these expressions can't be
+  // evaluated at compile time
+  constexpr exp_int e(3);
+  constexpr exp_int::unexpected_type err(3);
+  constexpr int i = 4;
+
+  // default constructor
+  static_assert(exp_int().value() == 0);
+  // copy constructor
+  static_assert(exp_int(e).value() == 3);
+  // move constructor
+  static_assert(exp_int(exp_int(4)).value() == 4);
+  // copy construct from value
+  static_assert(exp_int(i).value() == 4);
+  // copy construct from unexpected
+  static_assert(exp_int(err).error() == 3);
+  // move costruct from unexpected
+  static_assert(exp_int(unexpected(3)).error() == 3);
+  // observers
+  static_assert(*exp_int(3) == 3);
+  static_assert(exp_int(3).has_value() == true);
+  static_assert(exp_int(3).value_or(4) == 3);
+
+  typedef expected<const char*, int> exp_s;
+  constexpr exp_s s("hello");
+  constexpr const char* c = "hello";
+  static_assert(equals(exp_s().value(), nullptr));
+  static_assert(equals(exp_s(s).value(), "hello"));
+  static_assert(equals(exp_s(exp_s("hello")).value(), "hello"));
+  static_assert(equals(exp_s("hello").value(), "hello"));
+  static_assert(equals(exp_s(c).value(), "hello"));
+}
+
+TEST(Expected, testWithNonConstructible) {
+   struct AssertNotConstructed {
+     AssertNotConstructed() = delete;
+   };
+
+   expected<int, AssertNotConstructed> v(42);
+   EXPECT_TRUE(v.has_value());
+   EXPECT_EQ(42, v.value());
+
+   expected<AssertNotConstructed, int> e(unexpected(42));
+   EXPECT_FALSE(e.has_value());
+   EXPECT_EQ(42, e.error());
+}
+
+TEST(Expected, testWithMoveOnlyType) {
+  typedef expected<std::unique_ptr<int>,std::unique_ptr<int>> exp_ptr;
+  exp_ptr e(std::make_unique<int>(3));
+  exp_ptr e2(unexpected(std::make_unique<int>(4)));
+
+  EXPECT_TRUE(e.has_value());
+  EXPECT_FALSE(e2.has_value());
+  EXPECT_EQ(3, *(e.value()));
+  EXPECT_EQ(4, *(e2.error()));
+
+  e2 = std::move(e);
+  EXPECT_TRUE(e.has_value());
+  EXPECT_TRUE(e2.has_value());
+  EXPECT_EQ(3, *(e2.value()));
+}
diff --git a/base/file.cpp b/base/file.cpp
index adc8984..6321fc6 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -49,29 +49,54 @@
 #include "android-base/unique_fd.h"
 #include "android-base/utf8.h"
 
+namespace {
+
 #ifdef _WIN32
-int mkstemp(char* template_name) {
-  if (_mktemp(template_name) == nullptr) {
+static int mkstemp(char* name_template, size_t size_in_chars) {
+  std::wstring path;
+  CHECK(android::base::UTF8ToWide(name_template, &path))
+      << "path can't be converted to wchar: " << name_template;
+  if (_wmktemp_s(path.data(), path.size() + 1) != 0) {
     return -1;
   }
+
   // Use open() to match the close() that TemporaryFile's destructor does.
   // Use O_BINARY to match base file APIs.
-  return open(template_name, O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
+  int fd = _wopen(path.c_str(), O_CREAT | O_EXCL | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
+  if (fd < 0) {
+    return -1;
+  }
+
+  std::string path_utf8;
+  CHECK(android::base::WideToUTF8(path, &path_utf8)) << "path can't be converted to utf8";
+  CHECK(strcpy_s(name_template, size_in_chars, path_utf8.c_str()) == 0)
+      << "utf8 path can't be assigned back to name_template";
+
+  return fd;
 }
 
-char* mkdtemp(char* template_name) {
-  if (_mktemp(template_name) == nullptr) {
+static char* mkdtemp(char* name_template, size_t size_in_chars) {
+  std::wstring path;
+  CHECK(android::base::UTF8ToWide(name_template, &path))
+      << "path can't be converted to wchar: " << name_template;
+
+  if (_wmktemp_s(path.data(), path.size() + 1) != 0) {
     return nullptr;
   }
-  if (_mkdir(template_name) == -1) {
+
+  if (_wmkdir(path.c_str()) != 0) {
     return nullptr;
   }
-  return template_name;
+
+  std::string path_utf8;
+  CHECK(android::base::WideToUTF8(path, &path_utf8)) << "path can't be converted to utf8";
+  CHECK(strcpy_s(name_template, size_in_chars, path_utf8.c_str()) == 0)
+      << "utf8 path can't be assigned back to name_template";
+
+  return name_template;
 }
 #endif
 
-namespace {
-
 std::string GetSystemTempDir() {
 #if defined(__ANDROID__)
   const auto* tmpdir = getenv("TMPDIR");
@@ -83,15 +108,20 @@
   // so try current directory if /data/local/tmp is not accessible.
   return ".";
 #elif defined(_WIN32)
-  char tmp_dir[MAX_PATH];
-  DWORD result = GetTempPathA(sizeof(tmp_dir), tmp_dir);  // checks TMP env
-  CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError();
-  CHECK_LT(result, sizeof(tmp_dir)) << "path truncated to: " << result;
+  wchar_t tmp_dir_w[MAX_PATH];
+  DWORD result = GetTempPathW(std::size(tmp_dir_w), tmp_dir_w);  // checks TMP env
+  CHECK_NE(result, 0ul) << "GetTempPathW failed, error: " << GetLastError();
+  CHECK_LT(result, std::size(tmp_dir_w)) << "path truncated to: " << result;
 
   // GetTempPath() returns a path with a trailing slash, but init()
   // does not expect that, so remove it.
-  CHECK_EQ(tmp_dir[result - 1], '\\');
-  tmp_dir[result - 1] = '\0';
+  if (tmp_dir_w[result - 1] == L'\\') {
+    tmp_dir_w[result - 1] = L'\0';
+  }
+
+  std::string tmp_dir;
+  CHECK(android::base::WideToUTF8(tmp_dir_w, &tmp_dir)) << "path can't be converted to utf8";
+
   return tmp_dir;
 #else
   const auto* tmpdir = getenv("TMPDIR");
@@ -127,7 +157,11 @@
 
 void TemporaryFile::init(const std::string& tmp_dir) {
   snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(), OS_PATH_SEPARATOR);
+#if defined(_WIN32)
+  fd = mkstemp(path, sizeof(path));
+#else
   fd = mkstemp(path);
+#endif
 }
 
 TemporaryDir::TemporaryDir() {
@@ -167,7 +201,11 @@
 
 bool TemporaryDir::init(const std::string& tmp_dir) {
   snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(), OS_PATH_SEPARATOR);
+#if defined(_WIN32)
+  return (mkdtemp(path, sizeof(path)) != nullptr);
+#else
   return (mkdtemp(path) != nullptr);
+#endif
 }
 
 namespace android {
@@ -176,20 +214,20 @@
 // Versions of standard library APIs that support UTF-8 strings.
 using namespace android::base::utf8;
 
-bool ReadFdToString(int fd, std::string* content) {
+bool ReadFdToString(borrowed_fd fd, std::string* content) {
   content->clear();
 
   // Although original we had small files in mind, this code gets used for
   // very large files too, where the std::string growth heuristics might not
   // be suitable. https://code.google.com/p/android/issues/detail?id=258500.
   struct stat sb;
-  if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
+  if (fstat(fd.get(), &sb) != -1 && sb.st_size > 0) {
     content->reserve(sb.st_size);
   }
 
   char buf[BUFSIZ];
   ssize_t n;
-  while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
+  while ((n = TEMP_FAILURE_RETRY(read(fd.get(), &buf[0], sizeof(buf)))) > 0) {
     content->append(buf, n);
   }
   return (n == 0) ? true : false;
@@ -206,11 +244,11 @@
   return ReadFdToString(fd, content);
 }
 
-bool WriteStringToFd(const std::string& content, int fd) {
+bool WriteStringToFd(const std::string& content, borrowed_fd fd) {
   const char* p = content.data();
   size_t left = content.size();
   while (left > 0) {
-    ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left));
+    ssize_t n = TEMP_FAILURE_RETRY(write(fd.get(), p, left));
     if (n == -1) {
       return false;
     }
@@ -269,11 +307,11 @@
   return WriteStringToFd(content, fd) || CleanUpAfterFailedWrite(path);
 }
 
-bool ReadFully(int fd, void* data, size_t byte_count) {
+bool ReadFully(borrowed_fd fd, void* data, size_t byte_count) {
   uint8_t* p = reinterpret_cast<uint8_t*>(data);
   size_t remaining = byte_count;
   while (remaining > 0) {
-    ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining));
+    ssize_t n = TEMP_FAILURE_RETRY(read(fd.get(), p, remaining));
     if (n <= 0) return false;
     p += n;
     remaining -= n;
@@ -284,14 +322,14 @@
 #if defined(_WIN32)
 // Windows implementation of pread. Note that this DOES move the file descriptors read position,
 // but it does so atomically.
-static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) {
+static ssize_t pread(borrowed_fd fd, void* data, size_t byte_count, off64_t offset) {
   DWORD bytes_read;
   OVERLAPPED overlapped;
   memset(&overlapped, 0, sizeof(OVERLAPPED));
   overlapped.Offset = static_cast<DWORD>(offset);
   overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
-  if (!ReadFile(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), data, static_cast<DWORD>(byte_count),
-                &bytes_read, &overlapped)) {
+  if (!ReadFile(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), data,
+                static_cast<DWORD>(byte_count), &bytes_read, &overlapped)) {
     // In case someone tries to read errno (since this is masquerading as a POSIX call)
     errno = EIO;
     return -1;
@@ -300,10 +338,10 @@
 }
 #endif
 
-bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset) {
+bool ReadFullyAtOffset(borrowed_fd fd, void* data, size_t byte_count, off64_t offset) {
   uint8_t* p = reinterpret_cast<uint8_t*>(data);
   while (byte_count > 0) {
-    ssize_t n = TEMP_FAILURE_RETRY(pread(fd, p, byte_count, offset));
+    ssize_t n = TEMP_FAILURE_RETRY(pread(fd.get(), p, byte_count, offset));
     if (n <= 0) return false;
     p += n;
     byte_count -= n;
@@ -312,11 +350,11 @@
   return true;
 }
 
-bool WriteFully(int fd, const void* data, size_t byte_count) {
+bool WriteFully(borrowed_fd fd, const void* data, size_t byte_count) {
   const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
   size_t remaining = byte_count;
   while (remaining > 0) {
-    ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining));
+    ssize_t n = TEMP_FAILURE_RETRY(write(fd.get(), p, remaining));
     if (n == -1) return false;
     p += n;
     remaining -= n;
diff --git a/base/file_test.cpp b/base/file_test.cpp
index f64e81c..120228d 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -16,18 +16,25 @@
 
 #include "android-base/file.h"
 
+#include "android-base/utf8.h"
+
 #include <gtest/gtest.h>
 
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <wchar.h>
 
 #include <string>
 
 #if !defined(_WIN32)
 #include <pwd.h>
+#else
+#include <windows.h>
 #endif
 
+#include "android-base/logging.h"  // and must be after windows.h for ERROR
+
 TEST(file, ReadFileToString_ENOENT) {
   std::string s("hello");
   errno = 0;
@@ -38,7 +45,7 @@
 
 TEST(file, ReadFileToString_WriteStringToFile) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
   ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path))
     << strerror(errno);
   std::string s;
@@ -70,7 +77,7 @@
 #if !defined(_WIN32)
 TEST(file, WriteStringToFile2) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
   ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path, 0660,
                                                getuid(), getgid()))
       << strerror(errno);
@@ -86,9 +93,92 @@
 }
 #endif
 
+#if defined(_WIN32)
+TEST(file, NonUnicodeCharsWindows) {
+  constexpr auto kMaxEnvVariableValueSize = 32767;
+  std::wstring old_tmp;
+  old_tmp.resize(kMaxEnvVariableValueSize);
+  old_tmp.resize(GetEnvironmentVariableW(L"TMP", old_tmp.data(), old_tmp.size()));
+  if (old_tmp.empty()) {
+    // Can't continue with empty TMP folder.
+    return;
+  }
+
+  std::wstring new_tmp = old_tmp;
+  if (new_tmp.back() != L'\\') {
+    new_tmp.push_back(L'\\');
+  }
+
+  {
+    auto path(new_tmp + L"锦绣成都\\");
+    _wmkdir(path.c_str());
+    ASSERT_TRUE(SetEnvironmentVariableW(L"TMP", path.c_str()));
+
+    TemporaryFile tf;
+    ASSERT_NE(tf.fd, -1) << tf.path;
+    ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
+
+    ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
+
+    std::string s;
+    ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno);
+    EXPECT_EQ("abc", s);
+  }
+  {
+    auto path(new_tmp + L"директория с длинным именем\\");
+    _wmkdir(path.c_str());
+    ASSERT_TRUE(SetEnvironmentVariableW(L"TMP", path.c_str()));
+
+    TemporaryFile tf;
+    ASSERT_NE(tf.fd, -1) << tf.path;
+    ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
+
+    ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
+
+    std::string s;
+    ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno);
+    EXPECT_EQ("abc", s);
+  }
+  {
+    auto path(new_tmp + L"äüöß weiß\\");
+    _wmkdir(path.c_str());
+    ASSERT_TRUE(SetEnvironmentVariableW(L"TMP", path.c_str()));
+
+    TemporaryFile tf;
+    ASSERT_NE(tf.fd, -1) << tf.path;
+    ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
+
+    ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
+
+    std::string s;
+    ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno);
+    EXPECT_EQ("abc", s);
+  }
+
+  SetEnvironmentVariableW(L"TMP", old_tmp.c_str());
+}
+
+TEST(file, RootDirectoryWindows) {
+  constexpr auto kMaxEnvVariableValueSize = 32767;
+  std::wstring old_tmp;
+  bool tmp_is_empty = false;
+  old_tmp.resize(kMaxEnvVariableValueSize);
+  old_tmp.resize(GetEnvironmentVariableW(L"TMP", old_tmp.data(), old_tmp.size()));
+  if (old_tmp.empty()) {
+    tmp_is_empty = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+  }
+  SetEnvironmentVariableW(L"TMP", L"C:");
+
+  TemporaryFile tf;
+  ASSERT_NE(tf.fd, -1) << tf.path;
+
+  SetEnvironmentVariableW(L"TMP", tmp_is_empty ? nullptr : old_tmp.c_str());
+}
+#endif
+
 TEST(file, WriteStringToFd) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
   ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd));
 
   ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
@@ -100,7 +190,7 @@
 
 TEST(file, WriteFully) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
   ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
 
   ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno);
@@ -119,7 +209,7 @@
 
 TEST(file, RemoveFileIfExists) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
   close(tf.fd);
   tf.fd = -1;
   std::string err;
@@ -253,7 +343,7 @@
 
 TEST(file, ReadFileToString_capacity) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
 
   // For a huge file, the overhead should still be small.
   std::string s;
@@ -280,7 +370,7 @@
 
 TEST(file, ReadFileToString_capacity_0) {
   TemporaryFile tf;
-  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_NE(tf.fd, -1) << tf.path;
 
   // Because /proc reports its files as zero-length, we don't actually trust
   // any file that claims to be zero-length. Rather than add increasingly
diff --git a/base/format_benchmark.cpp b/base/format_benchmark.cpp
new file mode 100644
index 0000000..9590b23
--- /dev/null
+++ b/base/format_benchmark.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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 "android-base/format.h"
+
+#include <limits>
+
+#include <benchmark/benchmark.h>
+
+#include "android-base/stringprintf.h"
+
+using android::base::StringPrintf;
+
+static void BenchmarkFormatInt(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(fmt::format("{} {} {}", 42, std::numeric_limits<int>::min(),
+                                         std::numeric_limits<int>::max()));
+  }
+}
+
+BENCHMARK(BenchmarkFormatInt);
+
+static void BenchmarkStringPrintfInt(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(StringPrintf("%d %d %d", 42, std::numeric_limits<int>::min(),
+                                          std::numeric_limits<int>::max()));
+  }
+}
+
+BENCHMARK(BenchmarkStringPrintfInt);
+
+static void BenchmarkFormatFloat(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(fmt::format("{} {} {}", 42.42, std::numeric_limits<float>::min(),
+                                         std::numeric_limits<float>::max()));
+  }
+}
+
+BENCHMARK(BenchmarkFormatFloat);
+
+static void BenchmarkStringPrintfFloat(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(StringPrintf("%f %f %f", 42.42, std::numeric_limits<float>::min(),
+                                          std::numeric_limits<float>::max()));
+  }
+}
+
+BENCHMARK(BenchmarkStringPrintfFloat);
+
+static void BenchmarkFormatStrings(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(fmt::format("{} hello there {}", "hi,", "!!"));
+  }
+}
+
+BENCHMARK(BenchmarkFormatStrings);
+
+static void BenchmarkStringPrintfStrings(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(StringPrintf("%s hello there %s", "hi,", "!!"));
+  }
+}
+
+BENCHMARK(BenchmarkStringPrintfStrings);
+
+// Run the benchmark
+BENCHMARK_MAIN();
diff --git a/base/include/android-base/cmsg.h b/base/include/android-base/cmsg.h
index 7f93ddc..e4197b1 100644
--- a/base/include/android-base/cmsg.h
+++ b/base/include/android-base/cmsg.h
@@ -51,20 +51,20 @@
 // Note that the write can return short if the socket type is SOCK_STREAM. When
 // this happens, file descriptors are still sent to the other end, but with
 // truncated data. For this reason, using SOCK_SEQPACKET or SOCK_DGRAM is recommended.
-ssize_t SendFileDescriptorVector(int sock, const void* data, size_t len,
+ssize_t SendFileDescriptorVector(borrowed_fd sock, const void* data, size_t len,
                                  const std::vector<int>& fds);
 
 // Receive file descriptors from a Unix domain socket.
 //
 // If more FDs (or bytes, for datagram sockets) are received than expected,
 // -1 is returned with errno set to EMSGSIZE, and all received FDs are thrown away.
-ssize_t ReceiveFileDescriptorVector(int sock, void* data, size_t len, size_t max_fds,
+ssize_t ReceiveFileDescriptorVector(borrowed_fd sock, void* data, size_t len, size_t max_fds,
                                     std::vector<android::base::unique_fd>* fds);
 
 // Helper for SendFileDescriptorVector that constructs a std::vector for you, e.g.:
 //   SendFileDescriptors(sock, "foo", 3, std::move(fd1), std::move(fd2))
 template <typename... Args>
-ssize_t SendFileDescriptors(int sock, const void* data, size_t len, Args&&... sent_fds) {
+ssize_t SendFileDescriptors(borrowed_fd sock, const void* data, size_t len, Args&&... sent_fds) {
   // Do not allow implicit conversion to int: people might try to do something along the lines of:
   //   SendFileDescriptors(..., std::move(a_unique_fd))
   // and be surprised when the unique_fd isn't closed afterwards.
@@ -79,7 +79,7 @@
 // If fewer file descriptors are received than requested, -1 is returned with errno set to ENOMSG.
 // In both cases, all arguments are cleared and any received FDs are thrown away.
 template <typename... Args>
-ssize_t ReceiveFileDescriptors(int sock, void* data, size_t len, Args&&... received_fds) {
+ssize_t ReceiveFileDescriptors(borrowed_fd sock, void* data, size_t len, Args&&... received_fds) {
   std::vector<unique_fd*> fds;
   Append(fds, std::forward<Args>(received_fds)...);
 
diff --git a/base/include/android-base/endian.h b/base/include/android-base/endian.h
index cbbd8c9..8fa6365 100644
--- a/base/include/android-base/endian.h
+++ b/base/include/android-base/endian.h
@@ -18,6 +18,9 @@
 
 /* A cross-platform equivalent of bionic's <sys/endian.h>. */
 
+/* For __BIONIC__ and __GLIBC__ */
+#include <sys/cdefs.h>
+
 #if defined(__BIONIC__)
 
 #include <sys/endian.h>
@@ -38,26 +41,34 @@
 #define betoh16(x) be16toh(x)
 #define betoh32(x) be32toh(x)
 #define betoh64(x) be64toh(x)
+#define letoh16(x) le16toh(x)
+#define letoh32(x) le32toh(x)
+#define letoh64(x) le64toh(x)
 
 #else
 
-/* Mac OS and Windows have nothing. */
-
-#define __LITTLE_ENDIAN 1234
-#define LITTLE_ENDIAN __LITTLE_ENDIAN
-
-#define __BIG_ENDIAN 4321
-#define BIG_ENDIAN __BIG_ENDIAN
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#define BYTE_ORDER __BYTE_ORDER
-
+#if defined(__APPLE__)
+/* macOS has some of the basics. */
+#include <sys/_endian.h>
+#else
+/* Windows has some of the basics as well. */
+#include <sys/param.h>
+#include <winsock2.h>
+/* winsock2.h *must* be included before the following four macros. */
 #define htons(x) __builtin_bswap16(x)
 #define htonl(x) __builtin_bswap32(x)
-#define htonq(x) __builtin_bswap64(x)
-
 #define ntohs(x) __builtin_bswap16(x)
 #define ntohl(x) __builtin_bswap32(x)
+#endif
+
+/* Neither macOS nor Windows have the rest. */
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#define htonq(x) __builtin_bswap64(x)
+
 #define ntohq(x) __builtin_bswap64(x)
 
 #define htobe16(x) __builtin_bswap16(x)
diff --git a/base/include/android-base/expected.h b/base/include/android-base/expected.h
new file mode 100644
index 0000000..030ef35e
--- /dev/null
+++ b/base/include/android-base/expected.h
@@ -0,0 +1,773 @@
+/*
+ * 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 <algorithm>
+#include <initializer_list>
+#include <type_traits>
+#include <utility>
+#include <variant>
+
+// android::base::expected is an Android implementation of the std::expected
+// proposal.
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0323r7.html
+//
+// Usage:
+// using android::base::expected;
+// using android::base::unexpected;
+//
+// expected<double,std::string> safe_divide(double i, double j) {
+//   if (j == 0) return unexpected("divide by zero");
+//   else return i / j;
+// }
+//
+// void test() {
+//   auto q = safe_divide(10, 0);
+//   if (q) { printf("%f\n", q.value()); }
+//   else { printf("%s\n", q.error().c_str()); }
+// }
+//
+// When the proposal becomes part of the standard and is implemented by
+// libcxx, this will be removed and android::base::expected will be
+// type alias to std::expected.
+//
+
+namespace android {
+namespace base {
+
+// Synopsis
+template<class T, class E>
+    class expected;
+
+template<class E>
+    class unexpected;
+template<class E>
+  unexpected(E) -> unexpected<E>;
+
+template<class E>
+   class bad_expected_access;
+
+template<>
+   class bad_expected_access<void>;
+
+struct unexpect_t {
+   explicit unexpect_t() = default;
+};
+inline constexpr unexpect_t unexpect{};
+
+// macros for SFINAE
+#define _ENABLE_IF(...) \
+  , std::enable_if_t<(__VA_ARGS__)>* = nullptr
+
+// Define NODISCARD_EXPECTED to prevent expected<T,E> from being
+// ignored when used as a return value. This is off by default.
+#ifdef NODISCARD_EXPECTED
+#define _NODISCARD_ [[nodiscard]]
+#else
+#define _NODISCARD_
+#endif
+
+// Class expected
+template<class T, class E>
+class _NODISCARD_ expected {
+ public:
+  using value_type = T;
+  using error_type = E;
+  using unexpected_type = unexpected<E>;
+
+  template<class U>
+  using rebind = expected<U, error_type>;
+
+  // constructors
+  constexpr expected() = default;
+  constexpr expected(const expected& rhs) = default;
+  constexpr expected(expected&& rhs) noexcept = default;
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    !(!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* non-explicit */
+  )>
+  constexpr expected(const expected<U, G>& rhs) {
+    if (rhs.has_value()) var_ = rhs.value();
+    else var_ = unexpected(rhs.error());
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    (!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* explicit */
+  )>
+  constexpr explicit expected(const expected<U, G>& rhs) {
+    if (rhs.has_value()) var_ = rhs.value();
+    else var_ = unexpected(rhs.error());
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    !(!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* non-explicit */
+  )>
+  constexpr expected(expected<U, G>&& rhs) {
+    if (rhs.has_value()) var_ = std::move(rhs.value());
+    else var_ = unexpected(std::move(rhs.error()));
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_constructible_v<T, const U&> &&
+    std::is_constructible_v<E, const G&> &&
+    !std::is_constructible_v<T, expected<U, G>&> &&
+    !std::is_constructible_v<T, expected<U, G>&&> &&
+    !std::is_constructible_v<T, const expected<U, G>&> &&
+    !std::is_constructible_v<T, const expected<U, G>&&> &&
+    !std::is_convertible_v<expected<U, G>&, T> &&
+    !std::is_convertible_v<expected<U, G>&&, T> &&
+    !std::is_convertible_v<const expected<U, G>&, T> &&
+    !std::is_convertible_v<const expected<U, G>&&, T> &&
+    (!std::is_convertible_v<const U&, T> ||
+     !std::is_convertible_v<const G&, E>) /* explicit */
+  )>
+  constexpr explicit expected(expected<U, G>&& rhs) {
+    if (rhs.has_value()) var_ = std::move(rhs.value());
+    else var_ = unexpected(std::move(rhs.error()));
+  }
+
+  template <class U = T _ENABLE_IF(
+                std::is_constructible_v<T, U&&> &&
+                !std::is_same_v<std::remove_cv_t<std::remove_reference_t<U>>, std::in_place_t> &&
+                !std::is_same_v<expected<T, E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
+                !std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
+                std::is_convertible_v<U&&, T> /* non-explicit */
+                )>
+  constexpr expected(U&& v) : var_(std::in_place_index<0>, std::forward<U>(v)) {}
+
+  template <class U = T _ENABLE_IF(
+                std::is_constructible_v<T, U&&> &&
+                !std::is_same_v<std::remove_cv_t<std::remove_reference_t<U>>, std::in_place_t> &&
+                !std::is_same_v<expected<T, E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
+                !std::is_same_v<unexpected<E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
+                !std::is_convertible_v<U&&, T> /* explicit */
+                )>
+  constexpr explicit expected(U&& v) : var_(std::in_place_index<0>, T(std::forward<U>(v))) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, const G&> &&
+    std::is_convertible_v<const G&, E> /* non-explicit */
+  )>
+  constexpr expected(const unexpected<G>& e)
+  : var_(std::in_place_index<1>, e.value()) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, const G&> &&
+    !std::is_convertible_v<const G&, E> /* explicit */
+  )>
+  constexpr explicit expected(const unexpected<G>& e)
+  : var_(std::in_place_index<1>, E(e.value())) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, G&&> &&
+    std::is_convertible_v<G&&, E> /* non-explicit */
+  )>
+  constexpr expected(unexpected<G>&& e)
+  : var_(std::in_place_index<1>, std::move(e.value())) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, G&&> &&
+    !std::is_convertible_v<G&&, E> /* explicit */
+  )>
+  constexpr explicit expected(unexpected<G>&& e)
+  : var_(std::in_place_index<1>, E(std::move(e.value()))) {}
+
+  template<class... Args _ENABLE_IF(
+    std::is_constructible_v<T, Args&&...>
+  )>
+  constexpr explicit expected(std::in_place_t, Args&&... args)
+  : var_(std::in_place_index<0>, std::forward<Args>(args)...) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<T, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit expected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
+  : var_(std::in_place_index<0>, il, std::forward<Args>(args)...) {}
+
+  template<class... Args _ENABLE_IF(
+    std::is_constructible_v<E, Args...>
+  )>
+  constexpr explicit expected(unexpect_t, Args&&... args)
+  : var_(unexpected_type(std::forward<Args>(args)...)) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<E, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
+  : var_(unexpected_type(il, std::forward<Args>(args)...)) {}
+
+  // destructor
+  ~expected() = default;
+
+  // assignment
+  // Note: SFNAIE doesn't work here because assignment operator should be
+  // non-template. We could workaround this by defining a templated parent class
+  // having the assignment operator. This incomplete implementation however
+  // doesn't allow us to copy assign expected<T,E> even when T is non-copy
+  // assignable. The copy assignment will fail by the underlying std::variant
+  // anyway though the error message won't be clear.
+  expected& operator=(const expected& rhs) = default;
+
+  // Note for SFNAIE above applies to here as well
+  expected& operator=(expected&& rhs) noexcept(
+      std::is_nothrow_move_assignable_v<T>&& std::is_nothrow_move_assignable_v<E>) = default;
+
+  template <class U = T _ENABLE_IF(
+                !std::is_void_v<T> &&
+                !std::is_same_v<expected<T, E>, std::remove_cv_t<std::remove_reference_t<U>>> &&
+                !std::conjunction_v<std::is_scalar<T>, std::is_same<T, std::decay_t<U>>> &&
+                std::is_constructible_v<T, U> && std::is_assignable_v<T&, U> &&
+                std::is_nothrow_move_constructible_v<E>)>
+  expected& operator=(U&& rhs) {
+    var_ = T(std::forward<U>(rhs));
+    return *this;
+  }
+
+  template<class G = E>
+  expected& operator=(const unexpected<G>& rhs) {
+    var_ = rhs;
+    return *this;
+  }
+
+  template<class G = E _ENABLE_IF(
+    std::is_nothrow_move_constructible_v<G> &&
+    std::is_move_assignable_v<G>
+  )>
+  expected& operator=(unexpected<G>&& rhs) {
+    var_ = std::move(rhs);
+    return *this;
+  }
+
+  // modifiers
+  template<class... Args _ENABLE_IF(
+    std::is_nothrow_constructible_v<T, Args...>
+  )>
+  T& emplace(Args&&... args) {
+    expected(std::in_place, std::forward<Args>(args)...).swap(*this);
+    return value();
+  }
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>
+  )>
+  T& emplace(std::initializer_list<U> il, Args&&... args) {
+    expected(std::in_place, il, std::forward<Args>(args)...).swap(*this);
+    return value();
+  }
+
+  // swap
+  template<typename U = T, typename = std::enable_if_t<(
+    std::is_swappable_v<U> &&
+    std::is_swappable_v<E> &&
+    (std::is_move_constructible_v<U> ||
+     std::is_move_constructible_v<E>))>>
+  void swap(expected& rhs) noexcept(
+    std::is_nothrow_move_constructible_v<T> &&
+    std::is_nothrow_swappable_v<T> &&
+    std::is_nothrow_move_constructible_v<E> &&
+    std::is_nothrow_swappable_v<E>) {
+    var_.swap(rhs.var_);
+  }
+
+  // observers
+  constexpr const T* operator->() const { return std::addressof(value()); }
+  constexpr T* operator->() { return std::addressof(value()); }
+  constexpr const T& operator*() const& { return value(); }
+  constexpr T& operator*() & { return value(); }
+  constexpr const T&& operator*() const&& { return std::move(std::get<T>(var_)); }
+  constexpr T&& operator*() && { return std::move(std::get<T>(var_)); }
+
+  constexpr explicit operator bool() const noexcept { return has_value(); }
+  constexpr bool has_value() const noexcept { return var_.index() == 0; }
+
+  constexpr const T& value() const& { return std::get<T>(var_); }
+  constexpr T& value() & { return std::get<T>(var_); }
+  constexpr const T&& value() const&& { return std::move(std::get<T>(var_)); }
+  constexpr T&& value() && { return std::move(std::get<T>(var_)); }
+
+  constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
+  constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
+  constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
+  constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
+
+  template<class U _ENABLE_IF(
+    std::is_copy_constructible_v<T> &&
+    std::is_convertible_v<U, T>
+  )>
+  constexpr T value_or(U&& v) const& {
+    if (has_value()) return value();
+    else return static_cast<T>(std::forward<U>(v));
+  }
+
+  template<class U _ENABLE_IF(
+    std::is_move_constructible_v<T> &&
+    std::is_convertible_v<U, T>
+  )>
+  constexpr T value_or(U&& v) && {
+    if (has_value()) return std::move(value());
+    else return static_cast<T>(std::forward<U>(v));
+  }
+
+  // expected equality operators
+  template<class T1, class E1, class T2, class E2>
+  friend constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y);
+  template<class T1, class E1, class T2, class E2>
+  friend constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y);
+
+  // comparison with T
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator==(const expected<T1, E1>&, const T2&);
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator==(const T2&, const expected<T1, E1>&);
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator!=(const expected<T1, E1>&, const T2&);
+  template<class T1, class E1, class T2>
+  friend constexpr bool operator!=(const T2&, const expected<T1, E1>&);
+
+  // Comparison with unexpected<E>
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator==(const expected<T1, E1>&, const unexpected<E2>&);
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator==(const unexpected<E2>&, const expected<T1, E1>&);
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator!=(const expected<T1, E1>&, const unexpected<E2>&);
+  template<class T1, class E1, class E2>
+  friend constexpr bool operator!=(const unexpected<E2>&, const expected<T1, E1>&);
+
+  // Specialized algorithms
+  template<class T1, class E1>
+  friend void swap(expected<T1, E1>&, expected<T1, E1>&) noexcept;
+
+ private:
+  std::variant<value_type, unexpected_type> var_;
+};
+
+template<class T1, class E1, class T2, class E2>
+constexpr bool operator==(const expected<T1, E1>& x, const expected<T2, E2>& y) {
+  if (x.has_value() != y.has_value()) {
+    return false;
+  } else if (!x.has_value()) {
+    return x.error() == y.error();
+  } else {
+    return *x == *y;
+  }
+}
+
+template<class T1, class E1, class T2, class E2>
+constexpr bool operator!=(const expected<T1, E1>& x, const expected<T2, E2>& y) {
+  return !(x == y);
+}
+
+// comparison with T
+template<class T1, class E1, class T2>
+constexpr bool operator==(const expected<T1, E1>& x, const T2& y) {
+  return x.has_value() && (*x == y);
+}
+template<class T1, class E1, class T2>
+constexpr bool operator==(const T2& x, const expected<T1, E1>& y) {
+  return y.has_value() && (x == *y);
+}
+template<class T1, class E1, class T2>
+constexpr bool operator!=(const expected<T1, E1>& x, const T2& y) {
+  return !x.has_value() || (*x != y);
+}
+template<class T1, class E1, class T2>
+constexpr bool operator!=(const T2& x, const expected<T1, E1>& y) {
+  return !y.has_value() || (x != *y);
+}
+
+// Comparison with unexpected<E>
+template<class T1, class E1, class E2>
+constexpr bool operator==(const expected<T1, E1>& x, const unexpected<E2>& y) {
+  return !x.has_value() && (x.error() == y.value());
+}
+template<class T1, class E1, class E2>
+constexpr bool operator==(const unexpected<E2>& x, const expected<T1, E1>& y) {
+  return !y.has_value() && (x.value() == y.error());
+}
+template<class T1, class E1, class E2>
+constexpr bool operator!=(const expected<T1, E1>& x, const unexpected<E2>& y) {
+  return x.has_value() || (x.error() != y.value());
+}
+template<class T1, class E1, class E2>
+constexpr bool operator!=(const unexpected<E2>& x, const expected<T1, E1>& y) {
+  return y.has_value() || (x.value() != y.error());
+}
+
+template<class E>
+class _NODISCARD_ expected<void, E> {
+ public:
+  using value_type = void;
+  using error_type = E;
+  using unexpected_type = unexpected<E>;
+
+  // constructors
+  constexpr expected() = default;
+  constexpr expected(const expected& rhs) = default;
+  constexpr expected(expected&& rhs) noexcept = default;
+
+  template<class U, class G _ENABLE_IF(
+    std::is_void_v<U> &&
+    std::is_convertible_v<const G&, E> /* non-explicit */
+  )>
+  constexpr expected(const expected<U, G>& rhs) {
+    if (!rhs.has_value()) var_ = unexpected(rhs.error());
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_void_v<U> &&
+    !std::is_convertible_v<const G&, E> /* explicit */
+  )>
+  constexpr explicit expected(const expected<U, G>& rhs) {
+    if (!rhs.has_value()) var_ = unexpected(rhs.error());
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_void_v<U> &&
+    std::is_convertible_v<const G&&, E> /* non-explicit */
+  )>
+  constexpr expected(expected<U, G>&& rhs) {
+    if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
+  }
+
+  template<class U, class G _ENABLE_IF(
+    std::is_void_v<U> &&
+    !std::is_convertible_v<const G&&, E> /* explicit */
+  )>
+  constexpr explicit expected(expected<U, G>&& rhs) {
+    if (!rhs.has_value()) var_ = unexpected(std::move(rhs.error()));
+  }
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, const G&> &&
+    std::is_convertible_v<const G&, E> /* non-explicit */
+  )>
+  constexpr expected(const unexpected<G>& e)
+  : var_(std::in_place_index<1>, e.value()) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, const G&> &&
+    !std::is_convertible_v<const G&, E> /* explicit */
+  )>
+  constexpr explicit expected(const unexpected<G>& e)
+  : var_(std::in_place_index<1>, E(e.value())) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, G&&> &&
+    std::is_convertible_v<G&&, E> /* non-explicit */
+  )>
+  constexpr expected(unexpected<G>&& e)
+  : var_(std::in_place_index<1>, std::move(e.value())) {}
+
+  template<class G = E _ENABLE_IF(
+    std::is_constructible_v<E, G&&> &&
+    !std::is_convertible_v<G&&, E> /* explicit */
+  )>
+  constexpr explicit expected(unexpected<G>&& e)
+  : var_(std::in_place_index<1>, E(std::move(e.value()))) {}
+
+  template<class... Args _ENABLE_IF(
+    sizeof...(Args) == 0
+  )>
+  constexpr explicit expected(std::in_place_t, Args&&...) {}
+
+  template<class... Args _ENABLE_IF(
+    std::is_constructible_v<E, Args...>
+  )>
+  constexpr explicit expected(unexpect_t, Args&&... args)
+  : var_(unexpected_type(std::forward<Args>(args)...)) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<E, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
+  : var_(unexpected_type(il, std::forward<Args>(args)...)) {}
+
+  // destructor
+  ~expected() = default;
+
+  // assignment
+  // Note: SFNAIE doesn't work here because assignment operator should be
+  // non-template. We could workaround this by defining a templated parent class
+  // having the assignment operator. This incomplete implementation however
+  // doesn't allow us to copy assign expected<T,E> even when T is non-copy
+  // assignable. The copy assignment will fail by the underlying std::variant
+  // anyway though the error message won't be clear.
+  expected& operator=(const expected& rhs) = default;
+
+  // Note for SFNAIE above applies to here as well
+  expected& operator=(expected&& rhs) noexcept(std::is_nothrow_move_assignable_v<E>) = default;
+
+  template<class G = E>
+  expected& operator=(const unexpected<G>& rhs) {
+    var_ = rhs;
+    return *this;
+  }
+
+  template<class G = E _ENABLE_IF(
+    std::is_nothrow_move_constructible_v<G> &&
+    std::is_move_assignable_v<G>
+  )>
+  expected& operator=(unexpected<G>&& rhs) {
+    var_ = std::move(rhs);
+    return *this;
+  }
+
+  // modifiers
+  void emplace() {
+    var_ = std::monostate();
+  }
+
+  // swap
+  template<typename = std::enable_if_t<
+    std::is_swappable_v<E>>
+  >
+  void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<E>) {
+    var_.swap(rhs.var_);
+  }
+
+  // observers
+  constexpr explicit operator bool() const noexcept { return has_value(); }
+  constexpr bool has_value() const noexcept { return var_.index() == 0; }
+
+  constexpr void value() const& { if (!has_value()) std::get<0>(var_); }
+
+  constexpr const E& error() const& { return std::get<unexpected_type>(var_).value(); }
+  constexpr E& error() & { return std::get<unexpected_type>(var_).value(); }
+  constexpr const E&& error() const&& { return std::move(std::get<unexpected_type>(var_)).value(); }
+  constexpr E&& error() && { return std::move(std::get<unexpected_type>(var_)).value(); }
+
+  // expected equality operators
+  template<class E1, class E2>
+  friend constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y);
+
+  // Specialized algorithms
+  template<class T1, class E1>
+  friend void swap(expected<T1, E1>&, expected<T1, E1>&) noexcept;
+
+ private:
+  std::variant<std::monostate, unexpected_type> var_;
+};
+
+template<class E1, class E2>
+constexpr bool operator==(const expected<void, E1>& x, const expected<void, E2>& y) {
+  if (x.has_value() != y.has_value()) {
+    return false;
+  } else if (!x.has_value()) {
+    return x.error() == y.error();
+  } else {
+    return true;
+  }
+}
+
+template<class T1, class E1, class E2>
+constexpr bool operator==(const expected<T1, E1>& x, const expected<void, E2>& y) {
+  if (x.has_value() != y.has_value()) {
+    return false;
+  } else if (!x.has_value()) {
+    return x.error() == y.error();
+  } else {
+    return false;
+  }
+}
+
+template<class E1, class T2, class E2>
+constexpr bool operator==(const expected<void, E1>& x, const expected<T2, E2>& y) {
+  if (x.has_value() != y.has_value()) {
+    return false;
+  } else if (!x.has_value()) {
+    return x.error() == y.error();
+  } else {
+    return false;
+  }
+}
+
+template<class E>
+class unexpected {
+ public:
+  // constructors
+  constexpr unexpected(const unexpected&) = default;
+  constexpr unexpected(unexpected&&) noexcept(std::is_nothrow_move_constructible_v<E>) = default;
+
+  template <class Err = E _ENABLE_IF(
+                std::is_constructible_v<E, Err> &&
+                !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, std::in_place_t> &&
+                !std::is_same_v<std::remove_cv_t<std::remove_reference_t<E>>, unexpected>)>
+  constexpr unexpected(Err&& e) : val_(std::forward<Err>(e)) {}
+
+  template<class U, class... Args _ENABLE_IF(
+    std::is_constructible_v<E, std::initializer_list<U>&, Args...>
+  )>
+  constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
+  : val_(il, std::forward<Args>(args)...) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    std::is_convertible_v<Err, E> /* non-explicit */
+  )>
+  constexpr unexpected(const unexpected<Err>& rhs)
+  : val_(rhs.value()) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    !std::is_convertible_v<Err, E> /* explicit */
+  )>
+  constexpr explicit unexpected(const unexpected<Err>& rhs)
+  : val_(E(rhs.value())) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    std::is_convertible_v<Err, E> /* non-explicit */
+  )>
+  constexpr unexpected(unexpected<Err>&& rhs)
+  : val_(std::move(rhs.value())) {}
+
+  template<class Err _ENABLE_IF(
+    std::is_constructible_v<E, Err> &&
+    !std::is_constructible_v<E, unexpected<Err>&> &&
+    !std::is_constructible_v<E, unexpected<Err>> &&
+    !std::is_constructible_v<E, const unexpected<Err>&> &&
+    !std::is_constructible_v<E, const unexpected<Err>> &&
+    !std::is_convertible_v<unexpected<Err>&, E> &&
+    !std::is_convertible_v<unexpected<Err>, E> &&
+    !std::is_convertible_v<const unexpected<Err>&, E> &&
+    !std::is_convertible_v<const unexpected<Err>, E> &&
+    !std::is_convertible_v<Err, E> /* explicit */
+  )>
+  constexpr explicit unexpected(unexpected<Err>&& rhs)
+  : val_(E(std::move(rhs.value()))) {}
+
+  // assignment
+  constexpr unexpected& operator=(const unexpected&) = default;
+  constexpr unexpected& operator=(unexpected&&) noexcept(std::is_nothrow_move_assignable_v<E>) =
+      default;
+  template<class Err = E>
+  constexpr unexpected& operator=(const unexpected<Err>& rhs) {
+    val_ = rhs.value();
+    return *this;
+  }
+  template<class Err = E>
+  constexpr unexpected& operator=(unexpected<Err>&& rhs) {
+    val_ = std::forward<E>(rhs.value());
+    return *this;
+  }
+
+  // observer
+  constexpr const E& value() const& noexcept { return val_; }
+  constexpr E& value() & noexcept { return val_; }
+  constexpr const E&& value() const&& noexcept { return std::move(val_); }
+  constexpr E&& value() && noexcept { return std::move(val_); }
+
+  void swap(unexpected& other) noexcept(std::is_nothrow_swappable_v<E>) {
+    std::swap(val_, other.val_);
+  }
+
+  template<class E1, class E2>
+  friend constexpr bool
+  operator==(const unexpected<E1>& e1, const unexpected<E2>& e2);
+  template<class E1, class E2>
+  friend constexpr bool
+  operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2);
+
+  template<class E1>
+  friend void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y)));
+
+ private:
+  E val_;
+};
+
+template<class E1, class E2>
+constexpr bool
+operator==(const unexpected<E1>& e1, const unexpected<E2>& e2) {
+  return e1.value() == e2.value();
+}
+
+template<class E1, class E2>
+constexpr bool
+operator!=(const unexpected<E1>& e1, const unexpected<E2>& e2) {
+  return e1.value() != e2.value();
+}
+
+template<class E1>
+void swap(unexpected<E1>& x, unexpected<E1>& y) noexcept(noexcept(x.swap(y))) {
+  x.swap(y);
+}
+
+// TODO: bad_expected_access class
+
+#undef _ENABLE_IF
+#undef _NODISCARD_
+
+}  // namespace base
+}  // namespace android
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index f8748b5..c622562 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -21,8 +21,9 @@
 
 #include <string>
 
-#include <android-base/macros.h>
+#include "android-base/macros.h"
 #include "android-base/off64_t.h"
+#include "android-base/unique_fd.h"
 
 #if !defined(_WIN32) && !defined(O_BINARY)
 /** Windows needs O_BINARY, but Unix never mangles line endings. */
@@ -77,13 +78,13 @@
 namespace android {
 namespace base {
 
-bool ReadFdToString(int fd, std::string* content);
+bool ReadFdToString(borrowed_fd fd, std::string* content);
 bool ReadFileToString(const std::string& path, std::string* content,
                       bool follow_symlinks = false);
 
 bool WriteStringToFile(const std::string& content, const std::string& path,
                        bool follow_symlinks = false);
-bool WriteStringToFd(const std::string& content, int fd);
+bool WriteStringToFd(const std::string& content, borrowed_fd fd);
 
 #if !defined(_WIN32)
 bool WriteStringToFile(const std::string& content, const std::string& path,
@@ -91,7 +92,7 @@
                        bool follow_symlinks = false);
 #endif
 
-bool ReadFully(int fd, void* data, size_t byte_count);
+bool ReadFully(borrowed_fd fd, void* data, size_t byte_count);
 
 // Reads `byte_count` bytes from the file descriptor at the specified offset.
 // Returns false if there was an IO error or EOF was reached before reading `byte_count` bytes.
@@ -101,9 +102,9 @@
 // get modified. This means that ReadFullyAtOffset can be used concurrently with other calls to the
 // same function, but concurrently seeking or reading incrementally can lead to unexpected
 // behavior.
-bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset);
+bool ReadFullyAtOffset(borrowed_fd fd, void* data, size_t byte_count, off64_t offset);
 
-bool WriteFully(int fd, const void* data, size_t byte_count);
+bool WriteFully(borrowed_fd fd, const void* data, size_t byte_count);
 
 bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr);
 
diff --git a/fs_mgr/libfiemap_writer/utility.h b/base/include/android-base/format.h
similarity index 62%
copy from fs_mgr/libfiemap_writer/utility.h
copy to base/include/android-base/format.h
index 2d418da..330040d 100644
--- a/fs_mgr/libfiemap_writer/utility.h
+++ b/base/include/android-base/format.h
@@ -16,15 +16,13 @@
 
 #pragma once
 
-#include <string>
-
-namespace android {
-namespace fiemap_writer {
-
-// Given a file that will be created, determine the maximum size its containing
-// filesystem allows. Note this is a theoretical maximum size; free space is
-// ignored entirely.
-uint64_t DetermineMaximumFileSize(const std::string& file_path);
-
-}  // namespace fiemap_writer
-}  // namespace android
+// We include fmtlib here as an alias, since libbase will have fmtlib statically linked already.
+// It is accessed through its normal fmt:: namespace.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wshadow"
+#include <fmt/chrono.h>
+#pragma clang diagnostic pop
+#include <fmt/core.h>
+#include <fmt/format.h>
+#include <fmt/ostream.h>
+#include <fmt/printf.h>
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index f94cc25..ab6476c 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -469,7 +469,7 @@
 }  // namespace base
 }  // namespace android
 
-namespace std {
+namespace std {  // NOLINT(cert-dcl58-cpp)
 
 // Emit a warning of ostream<< with std::string*. The intention was most likely to print *string.
 //
diff --git a/base/include/android-base/mapped_file.h b/base/include/android-base/mapped_file.h
index 80513b1..8c37f43 100644
--- a/base/include/android-base/mapped_file.h
+++ b/base/include/android-base/mapped_file.h
@@ -16,26 +16,29 @@
 
 #pragma once
 
-#include "android-base/macros.h"
-#include "android-base/off64_t.h"
-
 #include <sys/types.h>
 
 #include <memory>
 
+#include "android-base/macros.h"
+#include "android-base/off64_t.h"
+#include "android-base/unique_fd.h"
+
 #if defined(_WIN32)
 #include <windows.h>
 #define PROT_READ 1
 #define PROT_WRITE 2
+using os_handle = HANDLE;
 #else
 #include <sys/mman.h>
+using os_handle = int;
 #endif
 
 namespace android {
 namespace base {
 
 /**
- * A region of a file mapped into memory.
+ * A region of a file mapped into memory (for grepping: also known as MmapFile or file mapping).
  */
 class MappedFile {
  public:
@@ -44,19 +47,34 @@
    * `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping
    * will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`.
    */
-  static std::unique_ptr<MappedFile> FromFd(int fd, off64_t offset, size_t length, int prot);
+  static std::unique_ptr<MappedFile> FromFd(borrowed_fd fd, off64_t offset, size_t length,
+                                            int prot);
+
+  /**
+   * Same thing, but using the raw OS file handle instead of a CRT wrapper.
+   */
+  static std::unique_ptr<MappedFile> FromOsHandle(os_handle h, off64_t offset, size_t length,
+                                                  int prot);
 
   /**
    * Removes the mapping.
    */
   ~MappedFile();
 
-  char* data() { return base_ + offset_; }
-  size_t size() { return size_; }
+  /**
+   * Not copyable but movable.
+   */
+  MappedFile(MappedFile&& other);
+  MappedFile& operator=(MappedFile&& other);
+
+  char* data() const { return base_ + offset_; }
+  size_t size() const { return size_; }
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
 
+  void Close();
+
   char* base_;
   size_t size_;
 
diff --git a/base/include/android-base/no_destructor.h b/base/include/android-base/no_destructor.h
new file mode 100644
index 0000000..ce0dc9f
--- /dev/null
+++ b/base/include/android-base/no_destructor.h
@@ -0,0 +1,94 @@
+#pragma once
+
+/*
+ * 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 <utility>
+
+#include "android-base/macros.h"
+
+namespace android {
+namespace base {
+
+// A wrapper that makes it easy to create an object of type T with static
+// storage duration that:
+// - is only constructed on first access
+// - never invokes the destructor
+// in order to satisfy the styleguide ban on global constructors and
+// destructors.
+//
+// Runtime constant example:
+// const std::string& GetLineSeparator() {
+//  // Forwards to std::string(size_t, char, const Allocator&) constructor.
+//   static const base::NoDestructor<std::string> s(5, '-');
+//   return *s;
+// }
+//
+// More complex initialization with a lambda:
+// const std::string& GetSessionNonce() {
+//   static const base::NoDestructor<std::string> nonce([] {
+//     std::string s(16);
+//     crypto::RandString(s.data(), s.size());
+//     return s;
+//   }());
+//   return *nonce;
+// }
+//
+// NoDestructor<T> stores the object inline, so it also avoids a pointer
+// indirection and a malloc. Also note that since C++11 static local variable
+// initialization is thread-safe and so is this pattern. Code should prefer to
+// use NoDestructor<T> over:
+// - A function scoped static T* or T& that is dynamically initialized.
+// - A global base::LazyInstance<T>.
+//
+// Note that since the destructor is never run, this *will* leak memory if used
+// as a stack or member variable. Furthermore, a NoDestructor<T> should never
+// have global scope as that may require a static initializer.
+template <typename T>
+class NoDestructor {
+ public:
+  // Not constexpr; just write static constexpr T x = ...; if the value should
+  // be a constexpr.
+  template <typename... Args>
+  explicit NoDestructor(Args&&... args) {
+    new (storage_) T(std::forward<Args>(args)...);
+  }
+
+  // Allows copy and move construction of the contained type, to allow
+  // construction from an initializer list, e.g. for std::vector.
+  explicit NoDestructor(const T& x) { new (storage_) T(x); }
+  explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
+
+  NoDestructor(const NoDestructor&) = delete;
+  NoDestructor& operator=(const NoDestructor&) = delete;
+
+  ~NoDestructor() = default;
+
+  const T& operator*() const { return *get(); }
+  T& operator*() { return *get(); }
+
+  const T* operator->() const { return get(); }
+  T* operator->() { return get(); }
+
+  const T* get() const { return reinterpret_cast<const T*>(storage_); }
+  T* get() { return reinterpret_cast<T*>(storage_); }
+
+ private:
+  alignas(T) char storage_[sizeof(T)];
+};
+
+}  // namespace base
+}  // namespace android
diff --git a/base/include/android-base/parsebool.h b/base/include/android-base/parsebool.h
new file mode 100644
index 0000000..b2bd021
--- /dev/null
+++ b/base/include/android-base/parsebool.h
@@ -0,0 +1,58 @@
+/*
+ * 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 <string_view>
+
+namespace android {
+namespace base {
+
+// Parse the given string as yes or no inactivation of some sort. Return one of the
+// ParseBoolResult enumeration values.
+//
+// The following values parse as true:
+//
+//   1
+//   on
+//   true
+//   y
+//   yes
+//
+//
+// The following values parse as false:
+//
+//   0
+//   false
+//   n
+//   no
+//   off
+//
+// Anything else is a parse error.
+//
+// The purpose of this function is to have a single canonical parser for yes-or-no indications
+// throughout the system.
+
+enum class ParseBoolResult {
+  kError,
+  kFalse,
+  kTrue,
+};
+
+ParseBoolResult ParseBool(std::string_view s);
+
+}  // namespace base
+}  // namespace android
diff --git a/base/include/android-base/process.h b/base/include/android-base/process.h
new file mode 100644
index 0000000..69ed3fb
--- /dev/null
+++ b/base/include/android-base/process.h
@@ -0,0 +1,60 @@
+/*
+ * 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 <dirent.h>
+#include <sys/types.h>
+
+#include <iterator>
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace base {
+
+class AllPids {
+  class PidIterator {
+   public:
+    PidIterator(DIR* dir) : dir_(dir, closedir) { Increment(); }
+    PidIterator& operator++() {
+      Increment();
+      return *this;
+    }
+    bool operator==(const PidIterator& other) const { return pid_ == other.pid_; }
+    bool operator!=(const PidIterator& other) const { return !(*this == other); }
+    long operator*() const { return pid_; }
+    // iterator traits
+    using difference_type = pid_t;
+    using value_type = pid_t;
+    using pointer = const pid_t*;
+    using reference = const pid_t&;
+    using iterator_category = std::input_iterator_tag;
+
+   private:
+    void Increment();
+
+    pid_t pid_ = -1;
+    std::unique_ptr<DIR, decltype(&closedir)> dir_;
+  };
+
+ public:
+  PidIterator begin() { return opendir("/proc"); }
+  PidIterator end() { return nullptr; }
+};
+
+}  // namespace base
+}  // namespace android
diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h
index 31e5273..31823df 100644
--- a/base/include/android-base/properties.h
+++ b/base/include/android-base/properties.h
@@ -49,9 +49,6 @@
                                         T max = std::numeric_limits<T>::max());
 
 // Sets the system property `key` to `value`.
-// Note that system property setting is inherently asynchronous so a return value of `true`
-// isn't particularly meaningful, and immediately reading back the value won't necessarily
-// tell you whether or not your call succeeded. A `false` return value definitely means failure.
 bool SetProperty(const std::string& key, const std::string& value);
 
 // Waits for the system property `key` to have the value `expected_value`.
diff --git a/base/include/android-base/quick_exit.h b/base/include/android-base/quick_exit.h
deleted file mode 100644
index a03b14f..0000000
--- a/base/include/android-base/quick_exit.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2016 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 <stdlib.h>
-
-// Provide emulation for at_quick_exit/quick_exit on platforms that don't have it.
-namespace android {
-namespace base {
-
-// Bionic and glibc have quick_exit, Darwin and Windows don't.
-#if !defined(__linux__)
-  void quick_exit(int exit_code) __attribute__((noreturn));
-  int at_quick_exit(void (*func)());
-#else
-  using ::at_quick_exit;
-  using ::quick_exit;
-#endif
-}
-}
diff --git a/base/include/android-base/result.h b/base/include/android-base/result.h
new file mode 100644
index 0000000..1b763af
--- /dev/null
+++ b/base/include/android-base/result.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This file contains classes for returning a successful result along with an optional
+// arbitrarily typed return value or for returning a failure result along with an optional string
+// indicating why the function failed.
+
+// There are 3 classes that implement this functionality and one additional helper type.
+//
+// Result<T> either contains a member of type T that can be accessed using similar semantics as
+// std::optional<T> or it contains a ResultError describing an error, which can be accessed via
+// Result<T>::error().
+//
+// ResultError is a type that contains both a std::string describing the error and a copy of errno
+// from when the error occurred.  ResultError can be used in an ostream directly to print its
+// string value.
+//
+// Result<void> is the correct return type for a function that either returns successfully or
+// returns an error value.  Returning {} from a function that returns Result<void> is the
+// correct way to indicate that a function without a return type has completed successfully.
+//
+// A successful Result<T> is constructed implicitly from any type that can be implicitly converted
+// to T or from the constructor arguments for T.  This allows you to return a type T directly from
+// a function that returns Result<T>.
+//
+// Error and ErrnoError are used to construct a Result<T> that has failed.  The Error class takes
+// an ostream as an input and are implicitly cast to a Result<T> containing that failure.
+// ErrnoError() is a helper function to create an Error class that appends ": " + strerror(errno)
+// to the end of the failure string to aid in interacting with C APIs.  Alternatively, an errno
+// value can be directly specified via the Error() constructor.
+//
+// Errorf and ErrnoErrorf accept the format string syntax of the fmblib (https://fmt.dev).
+// Errorf("{} errors", num) is equivalent to Error() << num << " errors".
+//
+// ResultError can be used in the ostream and when using Error/Errorf to construct a Result<T>.
+// In this case, the string that the ResultError takes is passed through the stream normally, but
+// the errno is passed to the Result<T>. This can be used to pass errno from a failing C function up
+// multiple callers. Note that when the outer Result<T> is created with ErrnoError/ErrnoErrorf then
+// the errno from the inner ResultError is not passed. Also when multiple ResultError objects are
+// used, the errno of the last one is respected.
+//
+// ResultError can also directly construct a Result<T>.  This is particularly useful if you have a
+// function that return Result<T> but you have a Result<U> and want to return its error.  In this
+// case, you can return the .error() from the Result<U> to construct the Result<T>.
+
+// An example of how to use these is below:
+// Result<U> CalculateResult(const T& input) {
+//   U output;
+//   if (!SomeOtherCppFunction(input, &output)) {
+//     return Errorf("SomeOtherCppFunction {} failed", input);
+//   }
+//   if (!c_api_function(output)) {
+//     return ErrnoErrorf("c_api_function {} failed", output);
+//   }
+//   return output;
+// }
+//
+// auto output = CalculateResult(input);
+// if (!output) return Error() << "CalculateResult failed: " << output.error();
+// UseOutput(*output);
+
+#pragma once
+
+#include <errno.h>
+
+#include <sstream>
+#include <string>
+
+#include "android-base/expected.h"
+#include "android-base/format.h"
+
+namespace android {
+namespace base {
+
+struct ResultError {
+  template <typename T>
+  ResultError(T&& message, int code) : message_(std::forward<T>(message)), code_(code) {}
+
+  template <typename T>
+  operator android::base::expected<T, ResultError>() {
+    return android::base::unexpected(ResultError(message_, code_));
+  }
+
+  std::string message() const { return message_; }
+  int code() const { return code_; }
+
+ private:
+  std::string message_;
+  int code_;
+};
+
+inline bool operator==(const ResultError& lhs, const ResultError& rhs) {
+  return lhs.message() == rhs.message() && lhs.code() == rhs.code();
+}
+
+inline bool operator!=(const ResultError& lhs, const ResultError& rhs) {
+  return !(lhs == rhs);
+}
+
+inline std::ostream& operator<<(std::ostream& os, const ResultError& t) {
+  os << t.message();
+  return os;
+}
+
+class Error {
+ public:
+  Error() : errno_(0), append_errno_(false) {}
+  Error(int errno_to_append) : errno_(errno_to_append), append_errno_(true) {}
+
+  template <typename T>
+  operator android::base::expected<T, ResultError>() {
+    return android::base::unexpected(ResultError(str(), errno_));
+  }
+
+  template <typename T>
+  Error& operator<<(T&& t) {
+    if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError>) {
+      errno_ = t.code();
+      return (*this) << t.message();
+    }
+    int saved = errno;
+    ss_ << t;
+    errno = saved;
+    return *this;
+  }
+
+  const std::string str() const {
+    std::string str = ss_.str();
+    if (append_errno_) {
+      if (str.empty()) {
+        return strerror(errno_);
+      }
+      return std::move(str) + ": " + strerror(errno_);
+    }
+    return str;
+  }
+
+  Error(const Error&) = delete;
+  Error(Error&&) = delete;
+  Error& operator=(const Error&) = delete;
+  Error& operator=(Error&&) = delete;
+
+  template <typename... Args>
+  friend Error Errorf(const char* fmt, const Args&... args);
+
+  template <typename... Args>
+  friend Error ErrnoErrorf(const char* fmt, const Args&... args);
+
+ private:
+  Error(bool append_errno, int errno_to_append, const std::string& message)
+      : errno_(errno_to_append), append_errno_(append_errno) {
+    (*this) << message;
+  }
+
+  std::stringstream ss_;
+  int errno_;
+  const bool append_errno_;
+};
+
+inline Error ErrnoError() {
+  return Error(errno);
+}
+
+inline int ErrorCode(int code) {
+  return code;
+}
+
+// Return the error code of the last ResultError object, if any.
+// Otherwise, return `code` as it is.
+template <typename T, typename... Args>
+inline int ErrorCode(int code, T&& t, const Args&... args) {
+  if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, ResultError>) {
+    return ErrorCode(t.code(), args...);
+  }
+  return ErrorCode(code, args...);
+}
+
+template <typename... Args>
+inline Error Errorf(const char* fmt, const Args&... args) {
+  return Error(false, ErrorCode(0, args...), fmt::format(fmt, args...));
+}
+
+template <typename... Args>
+inline Error ErrnoErrorf(const char* fmt, const Args&... args) {
+  return Error(true, errno, fmt::format(fmt, args...));
+}
+
+template <typename T>
+using Result = android::base::expected<T, ResultError>;
+
+}  // namespace base
+}  // namespace android
diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h
index 8e9716f..14d534a 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -18,6 +18,7 @@
 
 #include <sstream>
 #include <string>
+#include <string_view>
 #include <vector>
 
 namespace android {
@@ -68,5 +69,26 @@
 // Tests whether 'lhs' equals 'rhs', ignoring case.
 bool EqualsIgnoreCase(std::string_view lhs, std::string_view rhs);
 
+// Removes `prefix` from the start of the given string and returns true (if
+// it was present), false otherwise.
+inline bool ConsumePrefix(std::string_view* s, std::string_view prefix) {
+  if (!StartsWith(*s, prefix)) return false;
+  s->remove_prefix(prefix.size());
+  return true;
+}
+
+// Removes `suffix` from the end of the given string and returns true (if
+// it was present), false otherwise.
+inline bool ConsumeSuffix(std::string_view* s, std::string_view suffix) {
+  if (!EndsWith(*s, suffix)) return false;
+  s->remove_suffix(suffix.size());
+  return true;
+}
+
+// Replaces `from` with `to` in `s`, once if `all == false`, or as many times as
+// there are matches if `all == true`.
+[[nodiscard]] std::string StringReplace(std::string_view s, std::string_view from,
+                                        std::string_view to, bool all);
+
 }  // namespace base
 }  // namespace android
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h
index b20f278..f3d7cb0 100644
--- a/base/include/android-base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -53,30 +53,34 @@
   CapturedStdout() : CapturedStdFd(STDOUT_FILENO) {}
 };
 
-#define ASSERT_MATCH(str, pattern)                                             \
-  do {                                                                         \
-    if (!std::regex_search((str), std::regex((pattern)))) {                    \
-      FAIL() << "regex mismatch: expected " << (pattern) << " in:\n" << (str); \
-    }                                                                          \
+#define ASSERT_MATCH(str, pattern)                                           \
+  do {                                                                       \
+    auto __s = (str);                                                        \
+    if (!std::regex_search(__s, std::regex((pattern)))) {                    \
+      FAIL() << "regex mismatch: expected " << (pattern) << " in:\n" << __s; \
+    }                                                                        \
   } while (0)
 
-#define ASSERT_NOT_MATCH(str, pattern)                                                     \
-  do {                                                                                     \
-    if (std::regex_search((str), std::regex((pattern)))) {                                 \
-      FAIL() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
-    }                                                                                      \
+#define ASSERT_NOT_MATCH(str, pattern)                                                   \
+  do {                                                                                   \
+    auto __s = (str);                                                                    \
+    if (std::regex_search(__s, std::regex((pattern)))) {                                 \
+      FAIL() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << __s; \
+    }                                                                                    \
   } while (0)
 
-#define EXPECT_MATCH(str, pattern)                                                    \
-  do {                                                                                \
-    if (!std::regex_search((str), std::regex((pattern)))) {                           \
-      ADD_FAILURE() << "regex mismatch: expected " << (pattern) << " in:\n" << (str); \
-    }                                                                                 \
+#define EXPECT_MATCH(str, pattern)                                                  \
+  do {                                                                              \
+    auto __s = (str);                                                               \
+    if (!std::regex_search(__s, std::regex((pattern)))) {                           \
+      ADD_FAILURE() << "regex mismatch: expected " << (pattern) << " in:\n" << __s; \
+    }                                                                               \
   } while (0)
 
-#define EXPECT_NOT_MATCH(str, pattern)                                                            \
-  do {                                                                                            \
-    if (std::regex_search((str), std::regex((pattern)))) {                                        \
-      ADD_FAILURE() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
-    }                                                                                             \
+#define EXPECT_NOT_MATCH(str, pattern)                                                          \
+  do {                                                                                          \
+    auto __s = (str);                                                                           \
+    if (std::regex_search(__s, std::regex((pattern)))) {                                        \
+      ADD_FAILURE() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << __s; \
+    }                                                                                           \
   } while (0)
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 3fa3bea..1605daf 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -92,6 +92,8 @@
   explicit unique_fd_impl(int fd) { reset(fd); }
   ~unique_fd_impl() { reset(); }
 
+  unique_fd_impl(const unique_fd_impl&) = delete;
+  void operator=(const unique_fd_impl&) = delete;
   unique_fd_impl(unique_fd_impl&& other) noexcept { reset(other.release()); }
   unique_fd_impl& operator=(unique_fd_impl&& s) noexcept {
     int fd = s.fd_;
@@ -103,11 +105,23 @@
   void reset(int new_value = -1) { reset(new_value, nullptr); }
 
   int get() const { return fd_; }
+
+#if !defined(ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION)
+  // unique_fd's operator int is dangerous, but we have way too much code that
+  // depends on it, so make this opt-in at first.
   operator int() const { return get(); }  // NOLINT
+#endif
+
+  bool operator>=(int rhs) const { return get() >= rhs; }
+  bool operator<(int rhs) const { return get() < rhs; }
+  bool operator==(int rhs) const { return get() == rhs; }
+  bool operator!=(int rhs) const { return get() != rhs; }
 
   // Catch bogus error checks (i.e.: "!fd" instead of "fd != -1").
   bool operator!() const = delete;
 
+  bool ok() const { return get() >= 0; }
+
   int release() __attribute__((warn_unused_result)) {
     tag(fd_, this, nullptr);
     int ret = fd_;
@@ -157,9 +171,6 @@
   static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
     T::Close(fd);
   }
-
-  unique_fd_impl(const unique_fd_impl&);
-  void operator=(const unique_fd_impl&);
 };
 
 using unique_fd = unique_fd_impl<DefaultCloser>;
@@ -246,6 +257,22 @@
 
 #endif  // !defined(_WIN32)
 
+// A wrapper type that can be implicitly constructed from either int or unique_fd.
+struct borrowed_fd {
+  /* implicit */ borrowed_fd(int fd) : fd_(fd) {}  // NOLINT
+  template <typename T>
+  /* implicit */ borrowed_fd(const unique_fd_impl<T>& ufd) : fd_(ufd.get()) {}  // NOLINT
+
+  int get() const { return fd_; }
+
+  bool operator>=(int rhs) const { return get() >= rhs; }
+  bool operator<(int rhs) const { return get() < rhs; }
+  bool operator==(int rhs) const { return get() == rhs; }
+  bool operator!=(int rhs) const { return get() != rhs; }
+
+ private:
+  int fd_ = -1;
+};
 }  // namespace base
 }  // namespace android
 
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index d26e8ba..fff3453 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -16,11 +16,15 @@
 
 #include "android-base/mapped_file.h"
 
+#include <utility>
+
 #include <errno.h>
 
 namespace android {
 namespace base {
 
+static constexpr char kEmptyBuffer[] = {'0'};
+
 static off64_t InitPageSize() {
 #if defined(_WIN32)
   SYSTEM_INFO si;
@@ -31,21 +35,31 @@
 #endif
 }
 
-std::unique_ptr<MappedFile> MappedFile::FromFd(int fd, off64_t offset, size_t length, int prot) {
-  static off64_t page_size = InitPageSize();
+std::unique_ptr<MappedFile> MappedFile::FromFd(borrowed_fd fd, off64_t offset, size_t length,
+                                               int prot) {
+#if defined(_WIN32)
+  return FromOsHandle(reinterpret_cast<HANDLE>(_get_osfhandle(fd.get())), offset, length, prot);
+#else
+  return FromOsHandle(fd.get(), offset, length, prot);
+#endif
+}
+
+std::unique_ptr<MappedFile> MappedFile::FromOsHandle(os_handle h, off64_t offset, size_t length,
+                                                     int prot) {
+  static const off64_t page_size = InitPageSize();
   size_t slop = offset % page_size;
   off64_t file_offset = offset - slop;
   off64_t file_length = length + slop;
 
 #if defined(_WIN32)
-  HANDLE handle =
-      CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), nullptr,
-                        (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
+  HANDLE handle = CreateFileMappingW(
+      h, nullptr, (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
   if (handle == nullptr) {
     // http://b/119818070 "app crashes when reading asset of zero length".
     // Return a MappedFile that's only valid for reading the size.
-    if (length == 0) {
-      return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0, nullptr});
+    if (length == 0 && ::GetLastError() == ERROR_FILE_INVALID) {
+      return std::unique_ptr<MappedFile>(
+          new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0, nullptr));
     }
     return nullptr;
   }
@@ -56,27 +70,54 @@
     return nullptr;
   }
   return std::unique_ptr<MappedFile>(
-      new MappedFile{static_cast<char*>(base), length, slop, handle});
+      new MappedFile(static_cast<char*>(base), length, slop, handle));
 #else
-  void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset);
+  void* base = mmap(nullptr, file_length, prot, MAP_SHARED, h, file_offset);
   if (base == MAP_FAILED) {
     // http://b/119818070 "app crashes when reading asset of zero length".
     // mmap fails with EINVAL for a zero length region.
     if (errno == EINVAL && length == 0) {
-      return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0});
+      return std::unique_ptr<MappedFile>(new MappedFile(const_cast<char*>(kEmptyBuffer), 0, 0));
     }
     return nullptr;
   }
-  return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
+  return std::unique_ptr<MappedFile>(new MappedFile(static_cast<char*>(base), length, slop));
 #endif
 }
 
+MappedFile::MappedFile(MappedFile&& other)
+    : base_(std::exchange(other.base_, nullptr)),
+      size_(std::exchange(other.size_, 0)),
+      offset_(std::exchange(other.offset_, 0))
+#ifdef _WIN32
+      ,
+      handle_(std::exchange(other.handle_, nullptr))
+#endif
+{
+}
+
+MappedFile& MappedFile::operator=(MappedFile&& other) {
+  Close();
+  base_ = std::exchange(other.base_, nullptr);
+  size_ = std::exchange(other.size_, 0);
+  offset_ = std::exchange(other.offset_, 0);
+#ifdef _WIN32
+  handle_ = std::exchange(other.handle_, nullptr);
+#endif
+  return *this;
+}
+
 MappedFile::~MappedFile() {
+  Close();
+}
+
+void MappedFile::Close() {
 #if defined(_WIN32)
-  if (base_ != nullptr) UnmapViewOfFile(base_);
+  if (base_ != nullptr && size_ != 0) UnmapViewOfFile(base_);
   if (handle_ != nullptr) CloseHandle(handle_);
+  handle_ = nullptr;
 #else
-  if (base_ != nullptr) munmap(base_, size_ + offset_);
+  if (base_ != nullptr && size_ != 0) munmap(base_, size_ + offset_);
 #endif
 
   base_ = nullptr;
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
index cfde73c..d21703c 100644
--- a/base/mapped_file_test.cpp
+++ b/base/mapped_file_test.cpp
@@ -44,5 +44,6 @@
   ASSERT_TRUE(tf.fd != -1);
 
   auto m = android::base::MappedFile::FromFd(tf.fd, 4096, 0, PROT_READ);
-  ASSERT_EQ(0u, m->size());
+  EXPECT_EQ(0u, m->size());
+  EXPECT_NE(nullptr, m->data());
 }
diff --git a/base/no_destructor_test.cpp b/base/no_destructor_test.cpp
new file mode 100644
index 0000000..f19468a
--- /dev/null
+++ b/base/no_destructor_test.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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 "android-base/no_destructor.h"
+
+#include <gtest/gtest.h>
+
+struct __attribute__((packed)) Bomb {
+  Bomb() : magic_(123) {}
+
+  ~Bomb() { exit(42); }
+
+  int get() const { return magic_; }
+
+ private:
+  [[maybe_unused]] char padding_;
+  int magic_;
+};
+
+TEST(no_destructor, bomb) {
+  ASSERT_EXIT(({
+                {
+                  Bomb b;
+                  if (b.get() != 123) exit(1);
+                }
+
+                exit(0);
+              }),
+              ::testing::ExitedWithCode(42), "");
+}
+
+TEST(no_destructor, defused) {
+  ASSERT_EXIT(({
+                {
+                  android::base::NoDestructor<Bomb> b;
+                  if (b->get() != 123) exit(1);
+                }
+
+                exit(0);
+              }),
+              ::testing::ExitedWithCode(0), "");
+}
+
+TEST(no_destructor, operators) {
+  android::base::NoDestructor<Bomb> b;
+  const android::base::NoDestructor<Bomb>& c = b;
+  ASSERT_EQ(123, b.get()->get());
+  ASSERT_EQ(123, b->get());
+  ASSERT_EQ(123, (*b).get());
+  ASSERT_EQ(123, c.get()->get());
+  ASSERT_EQ(123, c->get());
+  ASSERT_EQ(123, (*c).get());
+}
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/base/parsebool.cpp
similarity index 62%
copy from libmeminfo/vts/vts_meminfo_test.cpp
copy to base/parsebool.cpp
index 3193c31..ff96fe9 100644
--- a/libmeminfo/vts/vts_meminfo_test.cpp
+++ b/base/parsebool.cpp
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
-#include <meminfo/procmeminfo.h>
+#include "android-base/parsebool.h"
+#include <errno.h>
 
 namespace android {
-namespace meminfo {
+namespace base {
 
-// /proc/<pid>/smaps_rollup support is required.
-TEST(SmapsRollup, IsSupported) {
-    // Use init's pid for this test since it's the only known pid.
-    ASSERT_TRUE(IsSmapsRollupSupported(1));
+ParseBoolResult ParseBool(std::string_view s) {
+  if (s == "1" || s == "y" || s == "yes" || s == "on" || s == "true") {
+    return ParseBoolResult::kTrue;
+  }
+  if (s == "0" || s == "n" || s == "no" || s == "off" || s == "false") {
+    return ParseBoolResult::kFalse;
+  }
+  return ParseBoolResult::kError;
 }
 
-}  // namespace meminfo
+}  // namespace base
 }  // namespace android
diff --git a/base/parsebool_test.cpp b/base/parsebool_test.cpp
new file mode 100644
index 0000000..a081994
--- /dev/null
+++ b/base/parsebool_test.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "android-base/parsebool.h"
+
+#include <errno.h>
+
+#include <gtest/gtest.h>
+#include <string_view>
+
+using android::base::ParseBool;
+using android::base::ParseBoolResult;
+
+TEST(parsebool, true_) {
+  static const char* yes[] = {
+      "1", "on", "true", "y", "yes",
+  };
+  for (const char* s : yes) {
+    ASSERT_EQ(ParseBoolResult::kTrue, ParseBool(s));
+  }
+}
+
+TEST(parsebool, false_) {
+  static const char* no[] = {
+      "0", "false", "n", "no", "off",
+  };
+  for (const char* s : no) {
+    ASSERT_EQ(ParseBoolResult::kFalse, ParseBool(s));
+  }
+}
+
+TEST(parsebool, invalid) {
+  ASSERT_EQ(ParseBoolResult::kError, ParseBool("blarg"));
+  ASSERT_EQ(ParseBoolResult::kError, ParseBool(""));
+}
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/base/process.cpp
similarity index 67%
copy from libmeminfo/vts/vts_meminfo_test.cpp
copy to base/process.cpp
index 3193c31..b8cabf6 100644
--- a/libmeminfo/vts/vts_meminfo_test.cpp
+++ b/base/process.cpp
@@ -14,18 +14,26 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
-#include <meminfo/procmeminfo.h>
+#include "android-base/process.h"
 
 namespace android {
-namespace meminfo {
+namespace base {
 
-// /proc/<pid>/smaps_rollup support is required.
-TEST(SmapsRollup, IsSupported) {
-    // Use init's pid for this test since it's the only known pid.
-    ASSERT_TRUE(IsSmapsRollupSupported(1));
+void AllPids::PidIterator::Increment() {
+  if (!dir_) {
+    return;
+  }
+
+  dirent* de;
+  while ((de = readdir(dir_.get())) != nullptr) {
+    pid_t pid = atoi(de->d_name);
+    if (pid != 0) {
+      pid_ = pid;
+      return;
+    }
+  }
+  pid_ = -1;
 }
 
-}  // namespace meminfo
+}  // namespace base
 }  // namespace android
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/base/process_test.cpp
similarity index 67%
copy from libmeminfo/vts/vts_meminfo_test.cpp
copy to base/process_test.cpp
index 3193c31..056f667 100644
--- a/libmeminfo/vts/vts_meminfo_test.cpp
+++ b/base/process_test.cpp
@@ -14,18 +14,22 @@
  * limitations under the License.
  */
 
+#include "android-base/process.h"
+
+#include <unistd.h>
+
 #include <gtest/gtest.h>
 
-#include <meminfo/procmeminfo.h>
+TEST(process, find_ourselves) {
+#if defined(__linux__)
+  bool found_our_pid = false;
+  for (const auto& pid : android::base::AllPids{}) {
+    if (pid == getpid()) {
+      found_our_pid = true;
+    }
+  }
 
-namespace android {
-namespace meminfo {
+  EXPECT_TRUE(found_our_pid);
 
-// /proc/<pid>/smaps_rollup support is required.
-TEST(SmapsRollup, IsSupported) {
-    // Use init's pid for this test since it's the only known pid.
-    ASSERT_TRUE(IsSmapsRollupSupported(1));
+#endif
 }
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/base/properties.cpp b/base/properties.cpp
index d5a5918..4731bf2 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -28,19 +28,22 @@
 #include <map>
 #include <string>
 
+#include <android-base/parsebool.h>
 #include <android-base/parseint.h>
 
 namespace android {
 namespace base {
 
 bool GetBoolProperty(const std::string& key, bool default_value) {
-  std::string value = GetProperty(key, "");
-  if (value == "1" || value == "y" || value == "yes" || value == "on" || value == "true") {
-    return true;
-  } else if (value == "0" || value == "n" || value == "no" || value == "off" || value == "false") {
-    return false;
+  switch (ParseBool(GetProperty(key, ""))) {
+    case ParseBoolResult::kError:
+      return default_value;
+    case ParseBoolResult::kFalse:
+      return false;
+    case ParseBoolResult::kTrue:
+      return true;
   }
-  return default_value;
+  __builtin_unreachable();
 }
 
 template <typename T>
diff --git a/base/quick_exit.cpp b/base/quick_exit.cpp
deleted file mode 100644
index e4dd62b..0000000
--- a/base/quick_exit.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2016 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 "android-base/quick_exit.h"
-
-#if !defined(__linux__)
-
-#include <mutex>
-#include <vector>
-
-namespace android {
-namespace base {
-
-static auto& quick_exit_mutex = *new std::mutex();
-static auto& quick_exit_handlers = *new std::vector<void (*)()>();
-
-void quick_exit(int exit_code) {
-  std::lock_guard<std::mutex> lock(quick_exit_mutex);
-  for (auto it = quick_exit_handlers.rbegin(); it != quick_exit_handlers.rend(); ++it) {
-    (*it)();
-  }
-  _Exit(exit_code);
-}
-
-int at_quick_exit(void (*func)()) {
-  std::lock_guard<std::mutex> lock(quick_exit_mutex);
-  quick_exit_handlers.push_back(func);
-  return 0;
-}
-
-}  // namespace base
-}  // namespace android
-#endif
diff --git a/base/quick_exit_test.cpp b/base/quick_exit_test.cpp
deleted file mode 100644
index 7ca8156..0000000
--- a/base/quick_exit_test.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 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 "android-base/quick_exit.h"
-
-#include <gtest/gtest.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "android-base/test_utils.h"
-
-// These tests are a bit sketchy, since each test run adds global state that affects subsequent
-// tests (including ones not in this file!). Exit with 0 in Exiter and stick the at_quick_exit test
-// at the end to hack around this.
-struct Exiter {
-  ~Exiter() {
-    _Exit(0);
-  }
-};
-
-TEST(quick_exit, smoke) {
-  ASSERT_EXIT(android::base::quick_exit(123), testing::ExitedWithCode(123), "");
-}
-
-TEST(quick_exit, skip_static_destructors) {
-  static Exiter exiter;
-  ASSERT_EXIT(android::base::quick_exit(123), testing::ExitedWithCode(123), "");
-}
-
-TEST(quick_exit, at_quick_exit) {
-  static int counter = 4;
-  // "Functions passed to at_quick_exit are called in reverse order of their registration."
-  ASSERT_EQ(0, android::base::at_quick_exit([]() { _exit(counter); }));
-  ASSERT_EQ(0, android::base::at_quick_exit([]() { counter += 2; }));
-  ASSERT_EQ(0, android::base::at_quick_exit([]() { counter *= 10; }));
-  ASSERT_EXIT(android::base::quick_exit(123), testing::ExitedWithCode(42), "");
-}
diff --git a/base/result_test.cpp b/base/result_test.cpp
new file mode 100644
index 0000000..2ee4057
--- /dev/null
+++ b/base/result_test.cpp
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2017 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 "android-base/result.h"
+
+#include "errno.h"
+
+#include <istream>
+#include <string>
+
+#include <gtest/gtest.h>
+
+using namespace std::string_literals;
+
+namespace android {
+namespace base {
+
+TEST(result, result_accessors) {
+  Result<std::string> result = "success";
+  ASSERT_TRUE(result);
+  ASSERT_TRUE(result.has_value());
+
+  EXPECT_EQ("success", *result);
+  EXPECT_EQ("success", result.value());
+
+  EXPECT_EQ('s', result->data()[0]);
+}
+
+TEST(result, result_accessors_rvalue) {
+  ASSERT_TRUE(Result<std::string>("success"));
+  ASSERT_TRUE(Result<std::string>("success").has_value());
+
+  EXPECT_EQ("success", *Result<std::string>("success"));
+  EXPECT_EQ("success", Result<std::string>("success").value());
+
+  EXPECT_EQ('s', Result<std::string>("success")->data()[0]);
+}
+
+TEST(result, result_void) {
+  Result<void> ok = {};
+  EXPECT_TRUE(ok);
+  ok.value();  // should not crash
+  ASSERT_DEATH(ok.error(), "");
+
+  Result<void> fail = Error() << "failure" << 1;
+  EXPECT_FALSE(fail);
+  EXPECT_EQ("failure1", fail.error().message());
+  EXPECT_EQ(0, fail.error().code());
+  EXPECT_TRUE(ok != fail);
+  ASSERT_DEATH(fail.value(), "");
+
+  auto test = [](bool ok) -> Result<void> {
+    if (ok) return {};
+    else return Error() << "failure" << 1;
+  };
+  EXPECT_TRUE(test(true));
+  EXPECT_FALSE(test(false));
+  test(true).value();  // should not crash
+  ASSERT_DEATH(test(true).error(), "");
+  ASSERT_DEATH(test(false).value(), "");
+  EXPECT_EQ("failure1", test(false).error().message());
+}
+
+TEST(result, result_error) {
+  Result<void> result = Error() << "failure" << 1;
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  EXPECT_EQ(0, result.error().code());
+  EXPECT_EQ("failure1", result.error().message());
+}
+
+TEST(result, result_error_empty) {
+  Result<void> result = Error();
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  EXPECT_EQ(0, result.error().code());
+  EXPECT_EQ("", result.error().message());
+}
+
+TEST(result, result_error_rvalue) {
+  // Error() and ErrnoError() aren't actually used to create a Result<T> object.
+  // Under the hood, they are an intermediate class that can be implicitly constructed into a
+  // Result<T>.  This is needed both to create the ostream and because Error() itself, by
+  // definition will not know what the type, T, of the underlying Result<T> object that it would
+  // create is.
+
+  auto MakeRvalueErrorResult = []() -> Result<void> { return Error() << "failure" << 1; };
+  ASSERT_FALSE(MakeRvalueErrorResult());
+  ASSERT_FALSE(MakeRvalueErrorResult().has_value());
+
+  EXPECT_EQ(0, MakeRvalueErrorResult().error().code());
+  EXPECT_EQ("failure1", MakeRvalueErrorResult().error().message());
+}
+
+TEST(result, result_errno_error) {
+  constexpr int test_errno = 6;
+  errno = test_errno;
+  Result<void> result = ErrnoError() << "failure" << 1;
+
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  EXPECT_EQ(test_errno, result.error().code());
+  EXPECT_EQ("failure1: "s + strerror(test_errno), result.error().message());
+}
+
+TEST(result, result_errno_error_no_text) {
+  constexpr int test_errno = 6;
+  errno = test_errno;
+  Result<void> result = ErrnoError();
+
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  EXPECT_EQ(test_errno, result.error().code());
+  EXPECT_EQ(strerror(test_errno), result.error().message());
+}
+
+TEST(result, result_error_from_other_result) {
+  auto error_text = "test error"s;
+  Result<void> result = Error() << error_text;
+
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  Result<std::string> result2 = result.error();
+
+  ASSERT_FALSE(result2);
+  ASSERT_FALSE(result2.has_value());
+
+  EXPECT_EQ(0, result2.error().code());
+  EXPECT_EQ(error_text, result2.error().message());
+}
+
+TEST(result, result_error_through_ostream) {
+  auto error_text = "test error"s;
+  Result<void> result = Error() << error_text;
+
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  Result<std::string> result2 = Error() << result.error();
+
+  ASSERT_FALSE(result2);
+  ASSERT_FALSE(result2.has_value());
+
+  EXPECT_EQ(0, result2.error().code());
+  EXPECT_EQ(error_text, result2.error().message());
+}
+
+TEST(result, result_errno_error_through_ostream) {
+  auto error_text = "test error"s;
+  constexpr int test_errno = 6;
+  errno = 6;
+  Result<void> result = ErrnoError() << error_text;
+
+  errno = 0;
+
+  ASSERT_FALSE(result);
+  ASSERT_FALSE(result.has_value());
+
+  Result<std::string> result2 = Error() << result.error();
+
+  ASSERT_FALSE(result2);
+  ASSERT_FALSE(result2.has_value());
+
+  EXPECT_EQ(test_errno, result2.error().code());
+  EXPECT_EQ(error_text + ": " + strerror(test_errno), result2.error().message());
+}
+
+TEST(result, constructor_forwarding) {
+  auto result = Result<std::string>(std::in_place, 5, 'a');
+
+  ASSERT_TRUE(result);
+  ASSERT_TRUE(result.has_value());
+
+  EXPECT_EQ("aaaaa", *result);
+}
+
+struct ConstructorTracker {
+  static size_t constructor_called;
+  static size_t copy_constructor_called;
+  static size_t move_constructor_called;
+  static size_t copy_assignment_called;
+  static size_t move_assignment_called;
+
+  template <typename T>
+  ConstructorTracker(T&& string) : string(string) {
+    ++constructor_called;
+  }
+
+  ConstructorTracker(const ConstructorTracker& ct) {
+    ++copy_constructor_called;
+    string = ct.string;
+  }
+  ConstructorTracker(ConstructorTracker&& ct) noexcept {
+    ++move_constructor_called;
+    string = std::move(ct.string);
+  }
+  ConstructorTracker& operator=(const ConstructorTracker& ct) {
+    ++copy_assignment_called;
+    string = ct.string;
+    return *this;
+  }
+  ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
+    ++move_assignment_called;
+    string = std::move(ct.string);
+    return *this;
+  }
+
+  std::string string;
+};
+
+size_t ConstructorTracker::constructor_called = 0;
+size_t ConstructorTracker::copy_constructor_called = 0;
+size_t ConstructorTracker::move_constructor_called = 0;
+size_t ConstructorTracker::copy_assignment_called = 0;
+size_t ConstructorTracker::move_assignment_called = 0;
+
+Result<ConstructorTracker> ReturnConstructorTracker(const std::string& in) {
+  if (in.empty()) {
+    return "literal string";
+  }
+  if (in == "test2") {
+    return ConstructorTracker(in + in + "2");
+  }
+  ConstructorTracker result(in + " " + in);
+  return result;
+};
+
+TEST(result, no_copy_on_return) {
+  // If returning parameters that may be used to implicitly construct the type T of Result<T>,
+  // then those parameters are forwarded to the construction of Result<T>.
+
+  // If returning an prvalue or xvalue, it will be move constructed during the construction of
+  // Result<T>.
+
+  // This check ensures that that is the case, and particularly that no copy constructors
+  // are called.
+
+  auto result1 = ReturnConstructorTracker("");
+  ASSERT_TRUE(result1);
+  EXPECT_EQ("literal string", result1->string);
+  EXPECT_EQ(1U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  auto result2 = ReturnConstructorTracker("test2");
+  ASSERT_TRUE(result2);
+  EXPECT_EQ("test2test22", result2->string);
+  EXPECT_EQ(2U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+
+  auto result3 = ReturnConstructorTracker("test3");
+  ASSERT_TRUE(result3);
+  EXPECT_EQ("test3 test3", result3->string);
+  EXPECT_EQ(3U, ConstructorTracker::constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
+  EXPECT_EQ(2U, ConstructorTracker::move_constructor_called);
+  EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
+  EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
+}
+
+// Below two tests require that we do not hide the move constructor with our forwarding reference
+// constructor.  This is done with by disabling the forwarding reference constructor if its first
+// and only type is Result<T>.
+TEST(result, result_result_with_success) {
+  auto return_result_result_with_success = []() -> Result<Result<void>> { return Result<void>(); };
+  auto result = return_result_result_with_success();
+  ASSERT_TRUE(result);
+  ASSERT_TRUE(*result);
+
+  auto inner_result = result.value();
+  ASSERT_TRUE(inner_result);
+}
+
+TEST(result, result_result_with_failure) {
+  auto return_result_result_with_error = []() -> Result<Result<void>> {
+    return Result<void>(ResultError("failure string", 6));
+  };
+  auto result = return_result_result_with_error();
+  ASSERT_TRUE(result);
+  ASSERT_FALSE(*result);
+  EXPECT_EQ("failure string", (*result).error().message());
+  EXPECT_EQ(6, (*result).error().code());
+}
+
+// This test requires that we disable the forwarding reference constructor if Result<T> is the
+// *only* type that we are forwarding.  In otherwords, if we are forwarding Result<T>, int to
+// construct a Result<T>, then we still need the constructor.
+TEST(result, result_two_parameter_constructor_same_type) {
+  struct TestStruct {
+    TestStruct(int value) : value_(value) {}
+    TestStruct(Result<TestStruct> result, int value) : value_(result->value_ * value) {}
+    int value_;
+  };
+
+  auto return_test_struct = []() -> Result<TestStruct> {
+    return Result<TestStruct>(std::in_place, Result<TestStruct>(std::in_place, 6), 6);
+  };
+
+  auto result = return_test_struct();
+  ASSERT_TRUE(result);
+  EXPECT_EQ(36, result->value_);
+}
+
+TEST(result, die_on_access_failed_result) {
+  Result<std::string> result = Error();
+  ASSERT_DEATH(*result, "");
+}
+
+TEST(result, die_on_get_error_succesful_result) {
+  Result<std::string> result = "success";
+  ASSERT_DEATH(result.error(), "");
+}
+
+template <class CharT>
+std::basic_ostream<CharT>& SetErrnoToTwo(std::basic_ostream<CharT>& ss) {
+  errno = 2;
+  return ss;
+}
+
+TEST(result, preserve_errno) {
+  errno = 1;
+  int old_errno = errno;
+  Result<int> result = Error() << "Failed" << SetErrnoToTwo<char>;
+  ASSERT_FALSE(result);
+  EXPECT_EQ(old_errno, errno);
+
+  errno = 1;
+  old_errno = errno;
+  Result<int> result2 = ErrnoError() << "Failed" << SetErrnoToTwo<char>;
+  ASSERT_FALSE(result2);
+  EXPECT_EQ(old_errno, errno);
+  EXPECT_EQ(old_errno, result2.error().code());
+}
+
+TEST(result, error_with_fmt) {
+  Result<int> result = Errorf("{} {}!", "hello", "world");
+  EXPECT_EQ("hello world!", result.error().message());
+
+  result = Errorf("{} {}!", std::string("hello"), std::string("world"));
+  EXPECT_EQ("hello world!", result.error().message());
+
+  result = Errorf("{h} {w}!", fmt::arg("w", "world"), fmt::arg("h", "hello"));
+  EXPECT_EQ("hello world!", result.error().message());
+
+  result = Errorf("hello world!");
+  EXPECT_EQ("hello world!", result.error().message());
+
+  Result<int> result2 = Errorf("error occurred with {}", result.error());
+  EXPECT_EQ("error occurred with hello world!", result2.error().message());
+
+  constexpr int test_errno = 6;
+  errno = test_errno;
+  result = ErrnoErrorf("{} {}!", "hello", "world");
+  EXPECT_EQ(test_errno, result.error().code());
+  EXPECT_EQ("hello world!: "s + strerror(test_errno), result.error().message());
+}
+
+TEST(result, error_with_fmt_carries_errno) {
+  constexpr int inner_errno = 6;
+  errno = inner_errno;
+  Result<int> inner_result = ErrnoErrorf("inner failure");
+  errno = 0;
+  EXPECT_EQ(inner_errno, inner_result.error().code());
+
+  // outer_result is created with Errorf, but its error code is got from inner_result.
+  Result<int> outer_result = Errorf("outer failure caused by {}", inner_result.error());
+  EXPECT_EQ(inner_errno, outer_result.error().code());
+  EXPECT_EQ("outer failure caused by inner failure: "s + strerror(inner_errno),
+            outer_result.error().message());
+
+  // now both result objects are created with ErrnoErrorf. errno from the inner_result
+  // is not passed to outer_result.
+  constexpr int outer_errno = 10;
+  errno = outer_errno;
+  outer_result = ErrnoErrorf("outer failure caused by {}", inner_result.error());
+  EXPECT_EQ(outer_errno, outer_result.error().code());
+  EXPECT_EQ("outer failure caused by inner failure: "s + strerror(inner_errno) + ": "s +
+                strerror(outer_errno),
+            outer_result.error().message());
+}
+
+TEST(result, errno_chaining_multiple) {
+  constexpr int errno1 = 6;
+  errno = errno1;
+  Result<int> inner1 = ErrnoErrorf("error1");
+
+  constexpr int errno2 = 10;
+  errno = errno2;
+  Result<int> inner2 = ErrnoErrorf("error2");
+
+  // takes the error code of inner2 since its the last one.
+  Result<int> outer = Errorf("two errors: {}, {}", inner1.error(), inner2.error());
+  EXPECT_EQ(errno2, outer.error().code());
+  EXPECT_EQ("two errors: error1: "s + strerror(errno1) + ", error2: "s + strerror(errno2),
+            outer.error().message());
+}
+
+}  // namespace base
+}  // namespace android
diff --git a/base/strings.cpp b/base/strings.cpp
index bb3167e..40b2bf2 100644
--- a/base/strings.cpp
+++ b/base/strings.cpp
@@ -116,5 +116,24 @@
   return lhs.size() == rhs.size() && strncasecmp(lhs.data(), rhs.data(), lhs.size()) == 0;
 }
 
+std::string StringReplace(std::string_view s, std::string_view from, std::string_view to,
+                          bool all) {
+  if (from.empty()) return std::string(s);
+
+  std::string result;
+  std::string_view::size_type start_pos = 0;
+  do {
+    std::string_view::size_type pos = s.find(from, start_pos);
+    if (pos == std::string_view::npos) break;
+
+    result.append(s.data() + start_pos, pos - start_pos);
+    result.append(to.data(), to.size());
+
+    start_pos = pos + from.size();
+  } while (all);
+  result.append(s.data() + start_pos, s.size() - start_pos);
+  return result;
+}
+
 }  // namespace base
 }  // namespace android
diff --git a/base/strings_test.cpp b/base/strings_test.cpp
index 9d74094..5ae3094 100644
--- a/base/strings_test.cpp
+++ b/base/strings_test.cpp
@@ -295,3 +295,62 @@
 TEST(strings, ubsan_28729303) {
   android::base::Split("/dev/null", ":");
 }
+
+TEST(strings, ConsumePrefix) {
+  std::string_view s{"foo.bar"};
+  ASSERT_FALSE(android::base::ConsumePrefix(&s, "bar."));
+  ASSERT_EQ("foo.bar", s);
+  ASSERT_TRUE(android::base::ConsumePrefix(&s, "foo."));
+  ASSERT_EQ("bar", s);
+}
+
+TEST(strings, ConsumeSuffix) {
+  std::string_view s{"foo.bar"};
+  ASSERT_FALSE(android::base::ConsumeSuffix(&s, ".foo"));
+  ASSERT_EQ("foo.bar", s);
+  ASSERT_TRUE(android::base::ConsumeSuffix(&s, ".bar"));
+  ASSERT_EQ("foo", s);
+}
+
+TEST(strings, StringReplace_false) {
+  // No change.
+  ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "z", "Z", false));
+  ASSERT_EQ("", android::base::StringReplace("", "z", "Z", false));
+  ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "", "Z", false));
+
+  // Equal lengths.
+  ASSERT_EQ("Abcabc", android::base::StringReplace("abcabc", "a", "A", false));
+  ASSERT_EQ("aBcabc", android::base::StringReplace("abcabc", "b", "B", false));
+  ASSERT_EQ("abCabc", android::base::StringReplace("abcabc", "c", "C", false));
+
+  // Longer replacement.
+  ASSERT_EQ("foobcabc", android::base::StringReplace("abcabc", "a", "foo", false));
+  ASSERT_EQ("afoocabc", android::base::StringReplace("abcabc", "b", "foo", false));
+  ASSERT_EQ("abfooabc", android::base::StringReplace("abcabc", "c", "foo", false));
+
+  // Shorter replacement.
+  ASSERT_EQ("xxyz", android::base::StringReplace("abcxyz", "abc", "x", false));
+  ASSERT_EQ("axyz", android::base::StringReplace("abcxyz", "bcx", "x", false));
+  ASSERT_EQ("abcx", android::base::StringReplace("abcxyz", "xyz", "x", false));
+}
+
+TEST(strings, StringReplace_true) {
+  // No change.
+  ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "z", "Z", true));
+  ASSERT_EQ("", android::base::StringReplace("", "z", "Z", true));
+  ASSERT_EQ("abcabc", android::base::StringReplace("abcabc", "", "Z", true));
+
+  // Equal lengths.
+  ASSERT_EQ("AbcAbc", android::base::StringReplace("abcabc", "a", "A", true));
+  ASSERT_EQ("aBcaBc", android::base::StringReplace("abcabc", "b", "B", true));
+  ASSERT_EQ("abCabC", android::base::StringReplace("abcabc", "c", "C", true));
+
+  // Longer replacement.
+  ASSERT_EQ("foobcfoobc", android::base::StringReplace("abcabc", "a", "foo", true));
+  ASSERT_EQ("afoocafooc", android::base::StringReplace("abcabc", "b", "foo", true));
+  ASSERT_EQ("abfooabfoo", android::base::StringReplace("abcabc", "c", "foo", true));
+
+  // Shorter replacement.
+  ASSERT_EQ("xxyzx", android::base::StringReplace("abcxyzabc", "abc", "x", true));
+  ASSERT_EQ("<xx>", android::base::StringReplace("<abcabc>", "abc", "x", true));
+}
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index cb09433..8979b0c 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -1253,7 +1253,12 @@
         echo 1 reboot,empty # negative test (ID for unknown is 1)
         ;;
       reboot)
-        echo 1 reboo        # negative test (ID for unknown is 1)
+        echo 1 reboog       # negative test (ID for unknown is 1)
+        ;;
+      'reboot,pmic_off_fault,.*')
+        echo ${id} reboot,pmic_off_fault,hello,world
+        echo ${id} reboot,pmic_off_fault,
+        echo 1 reboot,pmic_off_fault
         ;;
     esac
     echo ${id} "${match}"   # matches b/c of exact
@@ -1266,6 +1271,8 @@
 - (wait until screen is up, boot has completed)
 - read bootstat for kBootReasonMap entries and test them all" ]
 test_kBootReasonMap() {
+  checkDebugBuild || return
+  duration_test 15
   local tempfile="`mktemp`"
   local arg=--boot_reason_enum
   adb_su bootstat ${arg} </dev/null 2>/dev/null |
@@ -1295,7 +1302,8 @@
   report_bootstat_logs -t${T} \
     '-bootstat: Service started: bootstat --boot_reason_enum=' \
     '-bootstat: Unknown boot reason: reboot,empty' \
-    '-bootstat: Unknown boot reason: reboo'
+    '-bootstat: Unknown boot reason: reboog' \
+    '-bootstat: Unknown boot reason: reboot,pmic_off_fault'
 }
 
 [ "USAGE: ${progname} [-s SERIAL] [tests]...
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 7b60524..d08a59f 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -140,13 +140,13 @@
     {"mba_err", 13},
     {"Watchdog", 14},
     {"Panic", 15},
-    {"power_key", 16},
-    {"power_on", 17},
+    {"power_key", 16},  // aliasReasons to cold,powerkey (Mediatek)
+    {"power_on", 17},   // aliasReasons to cold,powerkey
     {"Reboot", 18},
     {"rtc", 19},
     {"edl", 20},
     {"oem_pon1", 21},
-    {"oem_powerkey", 22},
+    {"oem_powerkey", 22},  // aliasReasons to cold,powerkey
     {"oem_unknown_reset", 23},
     {"srto: HWWDT reset SC", 24},
     {"srto: HWWDT reset platform", 25},
@@ -201,15 +201,15 @@
     {"hard,hw_reset", 72},
     {"shutdown,suspend", 73},    // Suspend to RAM
     {"shutdown,hibernate", 74},  // Suspend to DISK
-    {"power_on_key", 75},
-    {"reboot_by_key", 76},
-    {"wdt_by_pass_pwk", 77},
-    {"reboot_longkey", 78},
-    {"powerkey", 79},
-    {"usb", 80},
-    {"wdt", 81},
-    {"tool_by_pass_pwk", 82},
-    {"2sec_reboot", 83},
+    {"power_on_key", 75},        // aliasReasons to cold,powerkey
+    {"reboot_by_key", 76},       // translated to reboot,by_key
+    {"wdt_by_pass_pwk", 77},     // Mediatek
+    {"reboot_longkey", 78},      // translated to reboot,longkey
+    {"powerkey", 79},            // aliasReasons to cold,powerkey
+    {"usb", 80},                 // aliasReasons to cold,charger (Mediatek)
+    {"wdt", 81},                 // Mediatek
+    {"tool_by_pass_pwk", 82},    // aliasReasons to reboot,tool (Mediatek)
+    {"2sec_reboot", 83},         // aliasReasons to cold,rtc,2sec (Mediatek)
     {"reboot,by_key", 84},
     {"reboot,longkey", 85},
     {"reboot,2sec", 86},  // Deprecate in two years, replaced with cold,rtc,2sec
@@ -219,28 +219,28 @@
     {"reboot,rescueparty", 90},
     {"charge", 91},
     {"oem_tz_crash", 92},
-    {"uvlo", 93},  // aliasReasons converts to reboot,undervoltage
+    {"uvlo", 93},  // aliasReasons to reboot,undervoltage
     {"oem_ps_hold", 94},
     {"abnormal_reset", 95},
     {"oemerr_unknown", 96},
     {"reboot_fastboot_mode", 97},
     {"watchdog_apps_bite", 98},
     {"xpu_err", 99},
-    {"power_on_usb", 100},
+    {"power_on_usb", 100},  // aliasReasons to cold,charger
     {"watchdog_rpm", 101},
     {"watchdog_nonsec", 102},
     {"watchdog_apps_bark", 103},
     {"reboot_dmverity_corrupted", 104},
-    {"reboot_smpl", 105},  // aliasReasons converts to reboot,powerloss
+    {"reboot_smpl", 105},  // aliasReasons to reboot,powerloss
     {"watchdog_sdi_apps_reset", 106},
-    {"smpl", 107},  // aliasReasons converts to reboot,powerloss
+    {"smpl", 107},  // aliasReasons to reboot,powerloss
     {"oem_modem_failed_to_powerup", 108},
     {"reboot_normal", 109},
     {"oem_lpass_cfg", 110},
     {"oem_xpu_ns_error", 111},
-    {"power_key_press", 112},
+    {"power_key_press", 112},  // aliasReasons to cold,powerkey
     {"hardware_reset", 113},
-    {"reboot_by_powerkey", 114},
+    {"reboot_by_powerkey", 114},  // aliasReasons to cold,powerkey (is this correct?)
     {"reboot_verity", 115},
     {"oem_rpm_undef_error", 116},
     {"oem_crash_on_the_lk", 117},
@@ -250,7 +250,7 @@
     {"factory_cable", 121},
     {"oem_ar6320_failed_to_powerup", 122},
     {"watchdog_rpm_bite", 123},
-    {"power_on_cable", 124},
+    {"power_on_cable", 124},  // aliasReasons to cold,charger
     {"reboot_unknown", 125},
     {"wireless_charger", 126},
     {"0x776655ff", 127},
@@ -276,10 +276,10 @@
     {"software_master", 147},
     {"cold,charger", 148},
     {"cold,rtc", 149},
-    {"cold,rtc,2sec", 150},
-    {"reboot,tool", 151},
-    {"reboot,wdt", 152},
-    {"reboot,unknown", 153},
+    {"cold,rtc,2sec", 150},   // Mediatek
+    {"reboot,tool", 151},     // Mediatek
+    {"reboot,wdt", 152},      // Mediatek
+    {"reboot,unknown", 153},  // Mediatek
     {"kernel_panic,audit", 154},
     {"kernel_panic,atomic", 155},
     {"kernel_panic,hung", 156},
@@ -304,6 +304,14 @@
     {"reboot,pmic_off_fault,.*", 175},
     {"reboot,pmic_off_s3rst,.*", 176},
     {"reboot,pmic_off_other,.*", 177},
+    {"reboot,userrequested,fastboot", 178},
+    {"reboot,userrequested,recovery", 179},
+    {"reboot,userrequested,recovery,ui", 180},
+    {"shutdown,userrequested,fastboot", 181},
+    {"shutdown,userrequested,recovery", 182},
+    {"reboot,unknown[0-9]*", 183},
+    {"reboot,longkey,.*", 184},
+    {"reboot,boringssl-self-check-failed", 185},
 };
 
 // Converts a string value representing the reason the system booted to an
@@ -832,12 +840,12 @@
     // following table smaller.
     static const std::vector<std::pair<const std::string, const std::string>> aliasReasons = {
         {"watchdog", "wdog"},
-        {"cold,powerkey", "powerkey|power_key|PowerKey"},
         {"kernel_panic", "panic"},
         {"shutdown,thermal", "thermal"},
         {"warm,s3_wakeup", "s3_wakeup"},
         {"hard,hw_reset", "hw_reset"},
-        {"cold,charger", "usb"},
+        {"cold,charger", "usb|power_on_cable"},
+        {"cold,powerkey", "powerkey|power_key|PowerKey|power_on"},
         {"cold,rtc", "rtc"},
         {"cold,rtc,2sec", "2sec_reboot"},
         {"!warm", "wdt_by_pass_pwk"},  // change flavour of blunt
@@ -1174,6 +1182,7 @@
   boot_event_store.AddBootEventWithValue(boot_complete_prefix, uptime_s.count());
 
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init");
+  RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.first_stage");
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.selinux");
   RecordInitBootTimeProp(&boot_event_store, "ro.boottime.init.cold_boot_wait");
 
diff --git a/demangle/.clang-format b/cli-test/.clang-format
similarity index 100%
rename from demangle/.clang-format
rename to cli-test/.clang-format
diff --git a/cli-test/Android.bp b/cli-test/Android.bp
new file mode 100644
index 0000000..37a1d1b
--- /dev/null
+++ b/cli-test/Android.bp
@@ -0,0 +1,7 @@
+cc_binary {
+    name: "cli-test",
+    host_supported: true,
+    srcs: ["cli-test.cpp"],
+    cflags: ["-Wall", "-Werror"],
+    shared_libs: ["libbase"],
+}
diff --git a/cli-test/README.md b/cli-test/README.md
new file mode 100644
index 0000000..643eb74
--- /dev/null
+++ b/cli-test/README.md
@@ -0,0 +1,90 @@
+# cli-test
+
+## What?
+
+`cli-test` makes integration testing of command-line tools easier.
+
+## Goals
+
+* Readable syntax. Common cases should be concise, and pretty much anyone
+  should be able to read tests even if they've never seen this tool before.
+
+* Minimal issues with quoting. The toybox tests -- being shell scripts --
+  quickly become a nightmare of quoting. Using a non ad hoc format (such as
+  JSON) would have introduced similar but different quoting issues. A custom
+  format, while annoying, side-steps this.
+
+* Sensible defaults. We expect your exit status to be 0 unless you say
+  otherwise. We expect nothing on stderr unless you say otherwise. And so on.
+
+* Convention over configuration. Related to sensible defaults, we don't let you
+  configure things that aren't absolutely necessary. So you can't keep your test
+  data anywhere except in the `files/` subdirectory of the directory containing
+  your test, for example.
+
+## Non Goals
+
+* Portability. Just being able to run on Linux (host and device) is sufficient
+  for our needs. macOS is probably easy enough if we ever need it, but Windows
+  probably doesn't make sense.
+
+## Syntax
+
+Any all-whitespace line, or line starting with `#` is ignored.
+
+A test looks like this:
+```
+name: unzip -l
+command: unzip -l $FILES/example.zip d1/d2/x.txt
+after: [ ! -f d1/d2/x.txt ]
+expected-stdout:
+	Archive:  $FILES/example.zip
+	  Length      Date    Time    Name
+	---------  ---------- -----   ----
+	     1024  2017-06-04 08:45   d1/d2/x.txt
+	---------                     -------
+	     1024                     1 file
+---
+```
+
+The `name:` line names the test, and is only for human consumption.
+
+The `command:` line is the command to be run. Additional commands can be
+supplied as zero or more `before:` lines (run before `command:`) and zero or
+more `after:` lines (run after `command:`). These are useful for both
+setup/teardown but also for testing post conditions (as in the example above).
+
+Any `command:`, `before:`, or `after:` line is expected to exit with status 0.
+Anything else is considered a test failure.
+
+The `expected-stdout:` line is followed by zero or more tab-prefixed lines that
+are otherwise the exact output expected from the command. (There's magic behind
+the scenes to rewrite the test files directory to `$FILES` because otherwise any
+path in the output would depend on the temporary directory used to run the test.)
+
+There is currently no `expected-stderr:` line. Standard error is implicitly
+expected to be empty, and any output will cause a test failure. (The support is
+there, but not wired up because we haven't needed it yet.)
+
+The fields can appear in any order, but every test must contain at least a
+`name:` line and a `command:` line.
+
+## Output
+
+The output is intended to resemble gtest.
+
+## Future Directions
+
+* It's often useful to be able to *match* against stdout/stderr/a file rather
+  than give exact expected output. We might want to add explicit support for
+  this. In the meantime, it's possible to use an `after:` with `grep -q` if
+  you redirect in your `command:`.
+
+* In addition to using a `before:` (which will fail a test), it can be useful
+  to be able to specify tests that would cause us to *skip* a test. An example
+  would be "am I running as root?".
+
+* It might be useful to be able to make exit status assertions other than 0?
+
+* There's currently no way (other than the `files/` directory) to share repeated
+  setup between tests.
diff --git a/cli-test/cli-test.cpp b/cli-test/cli-test.cpp
new file mode 100644
index 0000000..d6e27ee
--- /dev/null
+++ b/cli-test/cli-test.cpp
@@ -0,0 +1,320 @@
+/*
+ * 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 <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/test_utils.h>
+
+// Example:
+
+// name: unzip -n
+// before: mkdir -p d1/d2
+// before: echo b > d1/d2/a.txt
+// command: unzip -q -n $FILES/zip/example.zip d1/d2/a.txt && cat d1/d2/a.txt
+// expected-stdout:
+// 	b
+
+struct Test {
+  std::string test_filename;
+  std::string name;
+  std::string command;
+  std::vector<std::string> befores;
+  std::vector<std::string> afters;
+  std::string expected_stdout;
+  std::string expected_stderr;
+  int exit_status = 0;
+};
+
+static const char* g_progname;
+static bool g_verbose;
+
+static const char* g_file;
+static size_t g_line;
+
+enum Color { kRed, kGreen };
+
+static void Print(Color c, const char* lhs, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  if (isatty(0)) printf("%s", (c == kRed) ? "\e[31m" : "\e[32m");
+  printf("%s%s", lhs, isatty(0) ? "\e[0m" : "");
+  vfprintf(stdout, fmt, ap);
+  putchar('\n');
+  va_end(ap);
+}
+
+static void Die(int error, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  fprintf(stderr, "%s: ", g_progname);
+  vfprintf(stderr, fmt, ap);
+  if (error != 0) fprintf(stderr, ": %s", strerror(error));
+  fprintf(stderr, "\n");
+  va_end(ap);
+  _exit(1);
+}
+
+static void V(const char* fmt, ...) {
+  if (!g_verbose) return;
+
+  va_list ap;
+  va_start(ap, fmt);
+  fprintf(stderr, "           - ");
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, "\n");
+  va_end(ap);
+}
+
+static void SetField(const char* what, std::string* field, std::string_view value) {
+  if (!field->empty()) {
+    Die(0, "%s:%zu: %s already set to '%s'", g_file, g_line, what, field->c_str());
+  }
+  field->assign(value);
+}
+
+// Similar to ConsumePrefix, but also trims, so "key:value" and "key: value"
+// are equivalent.
+static bool Match(std::string* s, const std::string& prefix) {
+  if (!android::base::StartsWith(*s, prefix)) return false;
+  s->assign(android::base::Trim(s->substr(prefix.length())));
+  return true;
+}
+
+static void CollectTests(std::vector<Test>* tests, const char* test_filename) {
+  std::string absolute_test_filename;
+  if (!android::base::Realpath(test_filename, &absolute_test_filename)) {
+    Die(errno, "realpath '%s'", test_filename);
+  }
+
+  std::string content;
+  if (!android::base::ReadFileToString(test_filename, &content)) {
+    Die(errno, "couldn't read '%s'", test_filename);
+  }
+
+  size_t count = 0;
+  g_file = test_filename;
+  g_line = 0;
+  auto lines = android::base::Split(content, "\n");
+  std::unique_ptr<Test> test(new Test);
+  while (g_line < lines.size()) {
+    auto line = lines[g_line++];
+    if (line.empty() || line[0] == '#') continue;
+
+    if (line[0] == '-') {
+      if (test->name.empty() || test->command.empty()) {
+        Die(0, "%s:%zu: each test requires both a name and a command", g_file, g_line);
+      }
+      test->test_filename = absolute_test_filename;
+      tests->push_back(*test.release());
+      test.reset(new Test);
+      ++count;
+    } else if (Match(&line, "name:")) {
+      SetField("name", &test->name, line);
+    } else if (Match(&line, "command:")) {
+      SetField("command", &test->command, line);
+    } else if (Match(&line, "before:")) {
+      test->befores.push_back(line);
+    } else if (Match(&line, "after:")) {
+      test->afters.push_back(line);
+    } else if (Match(&line, "expected-stdout:")) {
+      // Collect tab-indented lines.
+      std::string text;
+      while (g_line < lines.size() && !lines[g_line].empty() && lines[g_line][0] == '\t') {
+        text += lines[g_line++].substr(1) + "\n";
+      }
+      SetField("expected stdout", &test->expected_stdout, text);
+    } else {
+      Die(0, "%s:%zu: syntax error: \"%s\"", g_file, g_line, line.c_str());
+    }
+  }
+  if (count == 0) Die(0, "no tests found in '%s'", g_file);
+}
+
+static const char* Plural(size_t n) {
+  return (n == 1) ? "" : "s";
+}
+
+static std::string ExitStatusToString(int status) {
+  if (WIFSIGNALED(status)) {
+    return android::base::StringPrintf("was killed by signal %d (%s)", WTERMSIG(status),
+                                       strsignal(WTERMSIG(status)));
+  }
+  if (WIFSTOPPED(status)) {
+    return android::base::StringPrintf("was stopped by signal %d (%s)", WSTOPSIG(status),
+                                       strsignal(WSTOPSIG(status)));
+  }
+  return android::base::StringPrintf("exited with status %d", WEXITSTATUS(status));
+}
+
+static bool RunCommands(const char* what, const std::vector<std::string>& commands) {
+  bool result = true;
+  for (auto& command : commands) {
+    V("running %s \"%s\"", what, command.c_str());
+    int exit_status = system(command.c_str());
+    if (exit_status != 0) {
+      result = false;
+      fprintf(stderr, "Command (%s) \"%s\" %s\n", what, command.c_str(),
+              ExitStatusToString(exit_status).c_str());
+    }
+  }
+  return result;
+}
+
+static bool CheckOutput(const char* what, std::string actual_output,
+                        const std::string& expected_output, const std::string& FILES) {
+  // Rewrite the output to reverse any expansion of $FILES.
+  actual_output = android::base::StringReplace(actual_output, FILES, "$FILES", true);
+
+  bool result = (actual_output == expected_output);
+  if (!result) {
+    fprintf(stderr, "Incorrect %s.\nExpected:\n%s\nActual:\n%s\n", what, expected_output.c_str(),
+            actual_output.c_str());
+  }
+  return result;
+}
+
+static int RunTests(const std::vector<Test>& tests) {
+  std::vector<std::string> failures;
+
+  Print(kGreen, "[==========]", " Running %zu tests.", tests.size());
+  android::base::Timer total_timer;
+  for (const auto& test : tests) {
+    bool failed = false;
+
+    Print(kGreen, "[ RUN      ]", " %s", test.name.c_str());
+    android::base::Timer test_timer;
+
+    // Set $FILES for this test.
+    std::string FILES = android::base::Dirname(test.test_filename) + "/files";
+    V("setenv(\"FILES\", \"%s\")", FILES.c_str());
+    setenv("FILES", FILES.c_str(), 1);
+
+    // Make a safe space to run the test.
+    TemporaryDir td;
+    V("chdir(\"%s\")", td.path);
+    if (chdir(td.path)) Die(errno, "chdir(\"%s\")", td.path);
+
+    // Perform any setup specified for this test.
+    if (!RunCommands("before", test.befores)) failed = true;
+
+    if (!failed) {
+      V("running command \"%s\"", test.command.c_str());
+      CapturedStdout test_stdout;
+      CapturedStderr test_stderr;
+      int exit_status = system(test.command.c_str());
+      test_stdout.Stop();
+      test_stderr.Stop();
+
+      V("exit status %d", exit_status);
+      if (exit_status != test.exit_status) {
+        failed = true;
+        fprintf(stderr, "Incorrect exit status: expected %d but %s\n", test.exit_status,
+                ExitStatusToString(exit_status).c_str());
+      }
+
+      if (!CheckOutput("stdout", test_stdout.str(), test.expected_stdout, FILES)) failed = true;
+      if (!CheckOutput("stderr", test_stderr.str(), test.expected_stderr, FILES)) failed = true;
+
+      if (!RunCommands("after", test.afters)) failed = true;
+    }
+
+    std::stringstream duration;
+    duration << test_timer;
+    if (failed) {
+      failures.push_back(test.name);
+      Print(kRed, "[  FAILED  ]", " %s (%s)", test.name.c_str(), duration.str().c_str());
+    } else {
+      Print(kGreen, "[       OK ]", " %s (%s)", test.name.c_str(), duration.str().c_str());
+    }
+  }
+
+  // Summarize the whole run and explicitly list all the failures.
+
+  std::stringstream duration;
+  duration << total_timer;
+  Print(kGreen, "[==========]", " %zu tests ran. (%s total)", tests.size(), duration.str().c_str());
+
+  size_t fail_count = failures.size();
+  size_t pass_count = tests.size() - fail_count;
+  Print(kGreen, "[  PASSED  ]", " %zu test%s.", pass_count, Plural(pass_count));
+  if (!failures.empty()) {
+    Print(kRed, "[  FAILED  ]", " %zu test%s.", fail_count, Plural(fail_count));
+    for (auto& failure : failures) {
+      Print(kRed, "[  FAILED  ]", " %s", failure.c_str());
+    }
+  }
+  return (fail_count == 0) ? 0 : 1;
+}
+
+static void ShowHelp(bool full) {
+  fprintf(full ? stdout : stderr, "usage: %s [-v] FILE...\n", g_progname);
+  if (!full) exit(EXIT_FAILURE);
+
+  printf(
+      "\n"
+      "Run tests.\n"
+      "\n"
+      "-v\tVerbose (show workings)\n");
+  exit(EXIT_SUCCESS);
+}
+
+int main(int argc, char* argv[]) {
+  g_progname = basename(argv[0]);
+
+  static const struct option opts[] = {
+      {"help", no_argument, 0, 'h'},
+      {"verbose", no_argument, 0, 'v'},
+      {},
+  };
+
+  int opt;
+  while ((opt = getopt_long(argc, argv, "hv", opts, nullptr)) != -1) {
+    switch (opt) {
+      case 'h':
+        ShowHelp(true);
+        break;
+      case 'v':
+        g_verbose = true;
+        break;
+      default:
+        ShowHelp(false);
+        break;
+    }
+  }
+
+  argv += optind;
+  if (!*argv) Die(0, "no test files provided");
+  std::vector<Test> tests;
+  for (; *argv; ++argv) CollectTests(&tests, *argv);
+  return RunTests(tests);
+}
diff --git a/code_coverage/Android.mk b/code_coverage/Android.mk
new file mode 100644
index 0000000..80ab36b
--- /dev/null
+++ b/code_coverage/Android.mk
@@ -0,0 +1,37 @@
+# policies to allow processes inside minijail to dump code coverage information
+#
+
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := code_coverage.policy
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MULTILIB := both
+
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm arm64))
+LOCAL_MODULE_STEM_32 := code_coverage.arm.policy
+LOCAL_MODULE_STEM_64 := code_coverage.arm64.policy
+endif
+
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), x86 x86_64))
+LOCAL_MODULE_STEM_32 := code_coverage.x86.policy
+LOCAL_MODULE_STEM_64 := code_coverage.x86_64.policy
+endif
+
+# different files for different configurations
+ifeq ($(NATIVE_COVERAGE),true)
+LOCAL_SRC_FILES_arm := seccomp_policy/code_coverage.arm.policy
+LOCAL_SRC_FILES_arm64 := seccomp_policy/code_coverage.arm64.policy
+LOCAL_SRC_FILES_x86 := seccomp_policy/code_coverage.x86.policy
+LOCAL_SRC_FILES_x86_64 := seccomp_policy/code_coverage.x86_64.policy
+else
+LOCAL_SRC_FILES_arm := empty_policy/code_coverage.arm.policy
+LOCAL_SRC_FILES_arm64 := empty_policy/code_coverage.arm64.policy
+LOCAL_SRC_FILES_x86 := empty_policy/code_coverage.x86.policy
+LOCAL_SRC_FILES_x86_64 := empty_policy/code_coverage.x86_64.policy
+endif
+
+LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
+include $(BUILD_PREBUILT)
diff --git a/code_coverage/empty_policy/code_coverage.arm.policy b/code_coverage/empty_policy/code_coverage.arm.policy
new file mode 100644
index 0000000..4c9132b
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.arm.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.arm.policy
diff --git a/code_coverage/empty_policy/code_coverage.arm64.policy b/code_coverage/empty_policy/code_coverage.arm64.policy
new file mode 100644
index 0000000..dc5c35a
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.arm64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.arm64.policy
diff --git a/code_coverage/empty_policy/code_coverage.x86.policy b/code_coverage/empty_policy/code_coverage.x86.policy
new file mode 100644
index 0000000..044f34c
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.x86.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.x86.policy
diff --git a/code_coverage/empty_policy/code_coverage.x86_64.policy b/code_coverage/empty_policy/code_coverage.x86_64.policy
new file mode 100644
index 0000000..6dcd22d
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.x86_64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.x86_64.policy
diff --git a/code_coverage/seccomp_policy/code_coverage.arm.policy b/code_coverage/seccomp_policy/code_coverage.arm.policy
new file mode 100644
index 0000000..d6784e3
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.arm.policy
@@ -0,0 +1,14 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+gettimeofday: 1
+prctl: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.arm64.policy b/code_coverage/seccomp_policy/code_coverage.arm64.policy
new file mode 100644
index 0000000..4c3dd26
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.arm64.policy
@@ -0,0 +1,13 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+prctl: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.policy.def b/code_coverage/seccomp_policy/code_coverage.policy.def
new file mode 100644
index 0000000..f136084
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.policy.def
@@ -0,0 +1,51 @@
+// SECCOMP_MODE_STRICT
+//
+// minijail allowances for code coverage
+// this is processed with generate.sh, so we can use appropriate directives
+// size specific: __LP64__ for 64 bit, else 32 bit
+// arch specific: __arm__, __aarch64__, __i386__, __x86_64__
+
+// includes *all* syscalls used during the coverage dumping
+// no skipping just because they might have been in another policy file.
+
+// coverage tool uses different operations on different passes
+// 1st: uses write() to fill the file
+// 2nd-Nth: uses mmap() to update in place
+
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+
+#if     defined(__LP64__)
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+#else
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+#endif
+
+#if     defined(__arm__)
+gettimeofday: 1
+#endif
+
+#if     defined(__i386__)
+madvise: 1
+#endif
+
+#if     defined(__arm__)
+prctl: 1
+#elif   defined(__aarch64__)
+prctl: 1
+#endif
+
diff --git a/code_coverage/seccomp_policy/code_coverage.x86.policy b/code_coverage/seccomp_policy/code_coverage.x86.policy
new file mode 100644
index 0000000..24ff8b9
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.x86.policy
@@ -0,0 +1,13 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl64: 1
+fstat64: 1
+geteuid32: 1
+_llseek: 1
+mmap2: 1
+sigreturn: 1
+madvise: 1
diff --git a/code_coverage/seccomp_policy/code_coverage.x86_64.policy b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
new file mode 100644
index 0000000..3081036
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.x86_64.policy
@@ -0,0 +1,12 @@
+close: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
diff --git a/code_coverage/seccomp_policy/generate.sh b/code_coverage/seccomp_policy/generate.sh
new file mode 100755
index 0000000..ae582c6
--- /dev/null
+++ b/code_coverage/seccomp_policy/generate.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# generate the arch-specific files from the generic one
+
+set -ex
+
+cd "$(dirname "$0")"
+CPP='cpp -undef -E -P code_coverage.policy.def'
+$CPP -D__arm__ -o code_coverage.arm.policy
+$CPP -D__aarch64__ -D__LP64__ -o code_coverage.arm64.policy
+$CPP -D__i386__ -o code_coverage.x86.policy
+$CPP -D__x86_64__ -D__LP64__ -o code_coverage.x86_64.policy
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 2e226da..0602e0a 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -194,6 +194,7 @@
 cc_test {
     name: "debuggerd_test",
     defaults: ["debuggerd_defaults"],
+    require_root: true,
 
     cflags: ["-Wno-missing-field-initializers"],
     srcs: [
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 60eb241..7e35a2f 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -22,9 +22,11 @@
 #include <sys/poll.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <time.h>
 #include <unistd.h>
 
 #include <chrono>
+#include <iomanip>
 
 #include <android-base/cmsg.h>
 #include <android-base/file.h>
@@ -42,8 +44,10 @@
 
 using namespace std::chrono_literals;
 
+using android::base::ReadFileToString;
 using android::base::SendFileDescriptors;
 using android::base::unique_fd;
+using android::base::WriteStringToFd;
 
 static bool send_signal(pid_t pid, const DebuggerdDumpType dump_type) {
   const int signal = (dump_type == kDebuggerdJavaBacktrace) ? SIGQUIT : DEBUGGER_SIGNAL;
@@ -65,6 +69,76 @@
   tv->tv_usec = static_cast<long>(microseconds.count());
 }
 
+static void get_wchan_header(pid_t pid, std::stringstream& buffer) {
+  struct tm now;
+  time_t t = time(nullptr);
+  localtime_r(&t, &now);
+  char timestamp[32];
+  strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &now);
+  std::string time_now(timestamp);
+
+  std::string path = "/proc/" + std::to_string(pid) + "/cmdline";
+
+  char proc_name_buf[1024];
+  const char* proc_name = nullptr;
+  std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(path.c_str(), "r"), &fclose);
+
+  if (fp) {
+    proc_name = fgets(proc_name_buf, sizeof(proc_name_buf), fp.get());
+  }
+
+  if (!proc_name) {
+    proc_name = "<unknown>";
+  }
+
+  buffer << "\n----- Waiting Channels: pid " << pid << " at " << time_now << " -----\n"
+         << "Cmd line: " << proc_name << "\n";
+}
+
+static void get_wchan_footer(pid_t pid, std::stringstream& buffer) {
+  buffer << "----- end " << std::to_string(pid) << " -----\n";
+}
+
+/**
+ * Returns the wchan data for each thread in the process,
+ * or empty string if unable to obtain any data.
+ */
+static std::string get_wchan_data(pid_t pid) {
+  std::stringstream buffer;
+  std::vector<pid_t> tids;
+
+  if (!android::procinfo::GetProcessTids(pid, &tids)) {
+    LOG(WARNING) << "libdebuggerd_client: Failed to get process tids";
+    return buffer.str();
+  }
+
+  std::stringstream data;
+  for (int tid : tids) {
+    std::string path = "/proc/" + std::to_string(pid) + "/task/" + std::to_string(tid) + "/wchan";
+    std::string wchan_str;
+    if (!ReadFileToString(path, &wchan_str, true)) {
+      PLOG(WARNING) << "libdebuggerd_client: Failed to read \"" << path << "\"";
+      continue;
+    }
+    data << "sysTid=" << std::left << std::setw(10) << tid << wchan_str << "\n";
+  }
+
+  if (std::string str = data.str(); !str.empty()) {
+    get_wchan_header(pid, buffer);
+    buffer << "\n" << str << "\n";
+    get_wchan_footer(pid, buffer);
+    buffer << "\n";
+  }
+
+  return buffer.str();
+}
+
+static void dump_wchan_data(const std::string& data, int fd, pid_t pid) {
+  if (!WriteStringToFd(data, fd)) {
+    LOG(WARNING) << "libdebuggerd_client: Failed to dump wchan data for pid: " << pid;
+  }
+}
+
 bool debuggerd_trigger_dump(pid_t tid, DebuggerdDumpType dump_type, unsigned int timeout_ms,
                             unique_fd output_fd) {
   pid_t pid = tid;
@@ -121,7 +195,10 @@
     return false;
   }
 
-  InterceptRequest req = {.pid = pid, .dump_type = dump_type};
+  InterceptRequest req = {
+      .dump_type = dump_type,
+      .pid = pid,
+  };
   if (!set_timeout(sockfd)) {
     PLOG(ERROR) << "libdebugger_client: failed to set timeout";
     return false;
@@ -261,6 +338,17 @@
   if (copy == -1) {
     return -1;
   }
+
+  // debuggerd_trigger_dump results in every thread in the process being interrupted
+  // by a signal, so we need to fetch the wchan data before calling that.
+  std::string wchan_data = get_wchan_data(tid);
+
   int timeout_ms = timeout_secs > 0 ? timeout_secs * 1000 : 0;
-  return debuggerd_trigger_dump(tid, dump_type, timeout_ms, std::move(copy)) ? 0 : -1;
+  int ret = debuggerd_trigger_dump(tid, dump_type, timeout_ms, std::move(copy)) ? 0 : -1;
+
+  // Dump wchan data, since only privileged processes (CAP_SYS_ADMIN) can read
+  // kernel stack traces (/proc/*/stack).
+  dump_wchan_data(wchan_data, fd, tid);
+
+  return ret;
 }
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp
index 9c2f0d6..2545cd6 100644
--- a/debuggerd/client/debuggerd_client_test.cpp
+++ b/debuggerd/client/debuggerd_client_test.cpp
@@ -73,15 +73,15 @@
   unique_fd pipe_read, pipe_write;
   ASSERT_TRUE(Pipe(&pipe_read, &pipe_write));
 
-  // 64 kB should be enough for everyone.
+  // 64 MiB should be enough for everyone.
   constexpr int PIPE_SIZE = 64 * 1024 * 1024;
   ASSERT_EQ(PIPE_SIZE, fcntl(pipe_read.get(), F_SETPIPE_SZ, PIPE_SIZE));
 
   // Wait for a bit to let the child spawn all of its threads.
-  std::this_thread::sleep_for(250ms);
+  std::this_thread::sleep_for(1s);
 
   ASSERT_TRUE(
-      debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 10000, std::move(pipe_write)));
+      debuggerd_trigger_dump(forkpid, kDebuggerdNativeBacktrace, 60000, std::move(pipe_write)));
   // Immediately kill the forked child, to make sure that the dump didn't return early.
   ASSERT_EQ(0, kill(forkpid, SIGKILL)) << strerror(errno);
 
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index f0bdfbf..3041664 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -193,6 +193,7 @@
     fprintf(stderr, "  kuser_memory_barrier  call kuser_memory_barrier\n");
     fprintf(stderr, "  kuser_cmpxchg64       call kuser_cmpxchg64\n");
 #endif
+    fprintf(stderr, "  xom                   read execute-only memory\n");
     fprintf(stderr, "\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL      call liblog LOG_ALWAYS_FATAL\n");
     fprintf(stderr, "  LOG_ALWAYS_FATAL_IF   call liblog LOG_ALWAYS_FATAL_IF\n");
@@ -314,6 +315,11 @@
     } else if (!strcasecmp(arg, "seccomp")) {
       set_system_seccomp_filter();
       syscall(99999);
+#if defined(__LP64__)
+    } else if (!strcasecmp(arg, "xom")) {
+      // Try to read part of our code, which will fail if XOM is active.
+      printf("*%lx = %lx\n", reinterpret_cast<long>(usage), *reinterpret_cast<long*>(usage));
+#endif
 #if defined(__arm__)
     } else if (!strcasecmp(arg, "kuser_helper_version")) {
         return __kuser_helper_version;
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 64df53e..99729dc 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -101,7 +101,10 @@
     FAIL() << "failed to contact tombstoned: " << strerror(errno);
   }
 
-  InterceptRequest req = {.pid = target_pid, .dump_type = intercept_type};
+  InterceptRequest req = {
+      .dump_type = intercept_type,
+      .pid = target_pid,
+  };
 
   unique_fd output_pipe_write;
   if (!Pipe(output_fd, &output_pipe_write)) {
@@ -176,7 +179,7 @@
   if (crasher_pid != -1) {
     kill(crasher_pid, SIGKILL);
     int status;
-    waitpid(crasher_pid, &status, WUNTRACED);
+    TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED));
   }
 
   android::base::SetProperty(kWaitForGdbKey, previous_wait_for_gdb ? "1" : "0");
@@ -195,8 +198,7 @@
 void CrasherTest::FinishIntercept(int* result) {
   InterceptResponse response;
 
-  // Timeout for tombstoned intercept is 10 seconds.
-  ssize_t rc = TIMEOUT(20, read(intercept_fd.get(), &response, sizeof(response)));
+  ssize_t rc = TIMEOUT(30, read(intercept_fd.get(), &response, sizeof(response)));
   if (rc == -1) {
     FAIL() << "failed to read response from tombstoned: " << strerror(errno);
   } else if (rc == 0) {
@@ -233,7 +235,7 @@
     FAIL() << "crasher pipe uninitialized";
   }
 
-  ssize_t rc = write(crasher_pipe.get(), "\n", 1);
+  ssize_t rc = TEMP_FAILURE_RETRY(write(crasher_pipe.get(), "\n", 1));
   if (rc == -1) {
     FAIL() << "failed to write to crasher pipe: " << strerror(errno);
   } else if (rc == 0) {
@@ -243,9 +245,10 @@
 
 void CrasherTest::AssertDeath(int signo) {
   int status;
-  pid_t pid = TIMEOUT(5, waitpid(crasher_pid, &status, 0));
+  pid_t pid = TIMEOUT(30, waitpid(crasher_pid, &status, 0));
   if (pid != crasher_pid) {
-    printf("failed to wait for crasher (pid %d)\n", crasher_pid);
+    printf("failed to wait for crasher (expected pid %d, return value %d): %s\n", crasher_pid, pid,
+           strerror(errno));
     sleep(100);
     FAIL() << "failed to wait for crasher: " << strerror(errno);
   }
@@ -440,7 +443,7 @@
   FinishCrasher();
 
   int status;
-  ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, WUNTRACED));
+  ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, WUNTRACED)));
   ASSERT_TRUE(WIFSTOPPED(status));
   ASSERT_EQ(SIGSTOP, WSTOPSIG(status));
 
@@ -602,13 +605,15 @@
   policy += "\nclone: 1";
   policy += "\nsigaltstack: 1";
   policy += "\nnanosleep: 1";
+  policy += "\ngetrlimit: 1";
+  policy += "\nugetrlimit: 1";
 
   FILE* tmp_file = tmpfile();
   if (!tmp_file) {
     PLOG(FATAL) << "tmpfile failed";
   }
 
-  unique_fd tmp_fd(dup(fileno(tmp_file)));
+  unique_fd tmp_fd(TEMP_FAILURE_RETRY(dup(fileno(tmp_file))));
   if (!android::base::WriteStringToFd(policy, tmp_fd.get())) {
     PLOG(FATAL) << "failed to write policy to tmpfile";
   }
@@ -821,7 +826,7 @@
   FinishCrasher();
 
   int status;
-  ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
+  ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
   ASSERT_TRUE(WIFSTOPPED(status));
   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
 
@@ -836,7 +841,7 @@
   regex += R"( \(.+debuggerd_test)";
   ASSERT_MATCH(result, regex.c_str());
 
-  ASSERT_EQ(crasher_pid, waitpid(crasher_pid, &status, 0));
+  ASSERT_EQ(crasher_pid, TEMP_FAILURE_RETRY(waitpid(crasher_pid, &status, 0)));
   ASSERT_TRUE(WIFSTOPPED(status));
   ASSERT_EQ(SIGABRT, WSTOPSIG(status));
 
@@ -850,7 +855,7 @@
 
   StartProcess([]() {
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
-    unique_fd fd(open("/dev/null", O_RDONLY | O_CLOEXEC));
+    unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY | O_CLOEXEC)));
     if (fd == -1) {
       abort();
     }
@@ -885,13 +890,13 @@
     raise(DEBUGGER_SIGNAL);
 
     errno = 0;
-    rc = waitpid(-1, &status, __WALL | __WNOTHREAD);
+    rc = TEMP_FAILURE_RETRY(waitpid(-1, &status, __WALL | __WNOTHREAD));
     if (rc != -1 || errno != ECHILD) {
       errx(2, "second waitpid returned %d (%s), expected failure with ECHILD", rc, strerror(errno));
     }
     _exit(0);
   } else {
-    rc = waitpid(forkpid, &status, 0);
+    rc = TEMP_FAILURE_RETRY(waitpid(forkpid, &status, 0));
     ASSERT_EQ(forkpid, rc);
     ASSERT_TRUE(WIFEXITED(status));
     ASSERT_EQ(0, WEXITSTATUS(status));
@@ -1098,3 +1103,30 @@
   // This should be good enough, though...
   ASSERT_LT(diff, 10) << "too many new tombstones; is something crashing in the background?";
 }
+
+static __attribute__((__noinline__)) void overflow_stack(void* p) {
+  void* buf[1];
+  buf[0] = p;
+  static volatile void* global = buf;
+  if (global) {
+    global = buf;
+    overflow_stack(&buf);
+  }
+}
+
+TEST_F(CrasherTest, stack_overflow) {
+  int intercept_result;
+  unique_fd output_fd;
+  StartProcess([]() { overflow_stack(nullptr); });
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_MATCH(result, R"(Cause: stack pointer[^\n]*stack overflow.\n)");
+}
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 598ea85..b90ca80 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -525,8 +525,8 @@
   log_signal_summary(info);
 
   debugger_thread_info thread_info = {
-      .pseudothread_tid = -1,
       .crashing_tid = __gettid(),
+      .pseudothread_tid = -1,
       .siginfo = info,
       .ucontext = context,
       .abort_msg = reinterpret_cast<uintptr_t>(abort_message),
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index f189c45..75bac87 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -20,6 +20,7 @@
 
 #include <inttypes.h>
 #include <signal.h>
+#include <stdarg.h>
 #include <stdbool.h>
 #include <sys/types.h>
 
@@ -71,6 +72,7 @@
 
 // Log information onto the tombstone.
 void _LOG(log_t* log, logtype ltype, const char* fmt, ...) __attribute__((format(printf, 3, 4)));
+void _VLOG(log_t* log, logtype ltype, const char* fmt, va_list ap);
 
 namespace unwindstack {
 class Unwinder;
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 88c206f..9dea7ac 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -345,9 +345,9 @@
 
 TEST_F(TombstoneTest, dump_thread_info_uid) {
   dump_thread_info(&log_, ThreadInfo{.uid = 1,
-                                     .pid = 2,
                                      .tid = 3,
                                      .thread_name = "some_thread",
+                                     .pid = 2,
                                      .process_name = "some_process"});
   std::string expected = "pid: 2, tid: 3, name: some_thread  >>> some_process <<<\nuid: 1\n";
   ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index d246722..236fcf7 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -86,7 +86,39 @@
   _LOG(log, logtype::HEADER, "Timestamp: %s\n", buf);
 }
 
-static void dump_probable_cause(log_t* log, const siginfo_t* si, unwindstack::Maps* maps) {
+static std::string get_stack_overflow_cause(uint64_t fault_addr, uint64_t sp,
+                                            unwindstack::Maps* maps) {
+  static constexpr uint64_t kMaxDifferenceBytes = 256;
+  uint64_t difference;
+  if (sp >= fault_addr) {
+    difference = sp - fault_addr;
+  } else {
+    difference = fault_addr - sp;
+  }
+  if (difference <= kMaxDifferenceBytes) {
+    // The faulting address is close to the current sp, check if the sp
+    // indicates a stack overflow.
+    // On arm, the sp does not get updated when the instruction faults.
+    // In this case, the sp will still be in a valid map, which is the
+    // last case below.
+    // On aarch64, the sp does get updated when the instruction faults.
+    // In this case, the sp will be in either an invalid map if triggered
+    // on the main thread, or in a guard map if in another thread, which
+    // will be the first case or second case from below.
+    unwindstack::MapInfo* map_info = maps->Find(sp);
+    if (map_info == nullptr) {
+      return "stack pointer is in a non-existent map; likely due to stack overflow.";
+    } else if ((map_info->flags & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)) {
+      return "stack pointer is not in a rw map; likely due to stack overflow.";
+    } else if ((sp - map_info->start) <= kMaxDifferenceBytes) {
+      return "stack pointer is close to top of stack; likely stack overflow.";
+    }
+  }
+  return "";
+}
+
+static void dump_probable_cause(log_t* log, const siginfo_t* si, unwindstack::Maps* maps,
+                                unwindstack::Regs* regs) {
   std::string cause;
   if (si->si_signo == SIGSEGV && si->si_code == SEGV_MAPERR) {
     if (si->si_addr < reinterpret_cast<void*>(4096)) {
@@ -101,11 +133,16 @@
       cause = "call to kuser_memory_barrier";
     } else if (si->si_addr == reinterpret_cast<void*>(0xffff0f60)) {
       cause = "call to kuser_cmpxchg64";
+    } else {
+      cause = get_stack_overflow_cause(reinterpret_cast<uint64_t>(si->si_addr), regs->sp(), maps);
     }
   } else if (si->si_signo == SIGSEGV && si->si_code == SEGV_ACCERR) {
-    unwindstack::MapInfo* map_info = maps->Find(reinterpret_cast<uint64_t>(si->si_addr));
+    uint64_t fault_addr = reinterpret_cast<uint64_t>(si->si_addr);
+    unwindstack::MapInfo* map_info = maps->Find(fault_addr);
     if (map_info != nullptr && map_info->flags == PROT_EXEC) {
       cause = "execute-only (no-read) memory access error; likely due to data in .text.";
+    } else {
+      cause = get_stack_overflow_cause(fault_addr, regs->sp(), maps);
     }
   } else if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
     cause = StringPrintf("seccomp prevented call to disallowed %s system call %d", ABI_STRING,
@@ -391,7 +428,7 @@
   std::vector<std::pair<std::string, uint64_t>> special_row;
 
 #if defined(__arm__) || defined(__aarch64__)
-  static constexpr const char* special_registers[] = {"ip", "lr", "sp", "pc"};
+  static constexpr const char* special_registers[] = {"ip", "lr", "sp", "pc", "pst"};
 #elif defined(__i386__)
   static constexpr const char* special_registers[] = {"ebp", "esp", "eip"};
 #elif defined(__x86_64__)
@@ -447,7 +484,7 @@
 
   if (thread_info.siginfo) {
     dump_signal_info(log, thread_info, unwinder->GetProcessMemory().get());
-    dump_probable_cause(log, thread_info.siginfo, unwinder->GetMaps());
+    dump_probable_cause(log, thread_info.siginfo, unwinder->GetMaps(), thread_info.registers.get());
   }
 
   if (primary_thread) {
@@ -558,7 +595,7 @@
       }
       AndroidLogEntry e;
       char buf[512];
-      if (android_log_processBinaryLogBuffer(&log_entry.entry_v1, &e, g_eventTagMap, buf,
+      if (android_log_processBinaryLogBuffer(&log_entry.entry, &e, g_eventTagMap, buf,
                                              sizeof(buf)) == 0) {
         _LOG(log, logtype::LOGS, "%s.%03d %5d %5d %c %-8.*s: %s\n", timeBuf,
              log_entry.entry.nsec / 1000000, log_entry.entry.pid, log_entry.entry.tid, 'I',
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 9b2779a..5ce26fc 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -67,6 +67,14 @@
 
 __attribute__((__weak__, visibility("default")))
 void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  _VLOG(log, ltype, fmt, ap);
+  va_end(ap);
+}
+
+__attribute__((__weak__, visibility("default")))
+void _VLOG(log_t* log, enum logtype ltype, const char* fmt, va_list ap) {
   bool write_to_tombstone = (log->tfd != -1);
   bool write_to_logcat = is_allowed_in_logcat(ltype)
                       && log->crashed_tid != -1
@@ -75,10 +83,7 @@
   static bool write_to_kmsg = should_write_to_kmsg();
 
   std::string msg;
-  va_list ap;
-  va_start(ap, fmt);
   android::base::StringAppendV(&msg, fmt, ap);
-  va_end(ap);
 
   if (msg.empty()) return;
 
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index bbeb181..d09b8e8 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -100,7 +100,7 @@
 
   static CrashQueue* for_tombstones() {
     static CrashQueue queue("/data/tombstones", "tombstone_" /* file_name_prefix */,
-                            GetIntProperty("tombstoned.max_tombstone_count", 10),
+                            GetIntProperty("tombstoned.max_tombstone_count", 32),
                             1 /* max_concurrent_dumps */);
     return &queue;
   }
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc
index 53ef01c..b4a1e71 100644
--- a/debuggerd/tombstoned/tombstoned.rc
+++ b/debuggerd/tombstoned/tombstoned.rc
@@ -2,10 +2,10 @@
     user tombstoned
     group system
 
-    # Don't start tombstoned until after the real /data is mounted.
-    class late_start
-
     socket tombstoned_crash seqpacket 0666 system system
     socket tombstoned_intercept seqpacket 0666 system system
     socket tombstoned_java_trace seqpacket 0666 system system
     writepid /dev/cpuset/system-background/tasks
+
+on post-fs-data
+    start tombstoned
diff --git a/demangle/Android.bp b/demangle/Android.bp
deleted file mode 100644
index fd79cf8..0000000
--- a/demangle/Android.bp
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// Copyright (C) 2017 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: "libdemangle_defaults",
-
-    host_supported: true,
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-    ],
-
-    target: {
-        linux_bionic: {
-            enabled: true,
-        },
-    },
-}
-
-cc_library {
-    name: "libdemangle",
-    defaults: ["libdemangle_defaults"],
-    vendor_available: true,
-    recovery_available: true,
-
-    srcs: [
-        "Demangler.cpp",
-    ],
-
-    local_include_dirs: [
-        "include",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-}
-
-cc_binary {
-    name: "demangle",
-    defaults: ["libdemangle_defaults"],
-    srcs: ["demangle.cpp"],
-    host_supported: true,
-
-    shared_libs: ["libdemangle"],
-}
-
-//-------------------------------------------------------------------------
-// Unit Tests
-//-------------------------------------------------------------------------
-cc_test {
-    name: "libdemangle_test",
-    defaults: ["libdemangle_defaults"],
-
-    srcs: [
-        "DemangleTest.cpp",
-    ],
-
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-
-    shared_libs: [
-        "libdemangle",
-    ],
-
-    test_suites: ["device-tests"],
-    required: [
-        "libdemangle",
-    ],
-}
diff --git a/demangle/Android.mk b/demangle/Android.mk
deleted file mode 100644
index d8082a9..0000000
--- a/demangle/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := demangle_fuzzer
-LOCAL_SRC_FILES := \
-    Demangler.cpp \
-    demangle_fuzzer.cpp \
-
-LOCAL_CFLAGS := \
-    -Wall \
-    -Werror \
-    -Wextra \
-
-include $(BUILD_FUZZ_TEST)
diff --git a/demangle/DemangleTest.cpp b/demangle/DemangleTest.cpp
deleted file mode 100644
index 1787031..0000000
--- a/demangle/DemangleTest.cpp
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdlib.h>
-
-#include <gtest/gtest.h>
-
-#include <demangle.h>
-
-#include "Demangler.h"
-
-TEST(DemangleTest, IllegalArgumentModifiers) {
-  Demangler demangler;
-
-  ASSERT_EQ("_Zpp4FUNKK", demangler.Parse("_Zpp4FUNKK"));
-  ASSERT_EQ("_Zpp4FUNVV", demangler.Parse("_Zpp4FUNVV"));
-}
-
-TEST(DemangleTest, VoidArgument) {
-  Demangler demangler;
-
-  ASSERT_EQ("func()", demangler.Parse("_ZN4funcEv"));
-  ASSERT_EQ("func(void&)", demangler.Parse("_ZN4funcERv"));
-  ASSERT_EQ("func(void, void)", demangler.Parse("_ZN4funcEvv"));
-  ASSERT_EQ("func(void*)", demangler.Parse("_ZN4funcEPv"));
-  ASSERT_EQ("func(void const)", demangler.Parse("_ZN4funcEKv"));
-  ASSERT_EQ("func(void volatile)", demangler.Parse("_ZN4funcEVv"));
-}
-
-TEST(DemangleTest, ArgumentModifiers) {
-  Demangler demangler;
-
-  ASSERT_EQ("func(char)", demangler.Parse("_ZN4funcEc"));
-  ASSERT_EQ("func(char*)", demangler.Parse("_ZN4funcEPc"));
-  ASSERT_EQ("func(char**)", demangler.Parse("_ZN4funcEPPc"));
-  ASSERT_EQ("func(char***)", demangler.Parse("_ZN4funcEPPPc"));
-  ASSERT_EQ("func(char&)", demangler.Parse("_ZN4funcERc"));
-  ASSERT_EQ("func(char*&)", demangler.Parse("_ZN4funcERPc"));
-  ASSERT_EQ("func(char&)", demangler.Parse("_ZN4funcERRc"));
-  ASSERT_EQ("func(char*&*)", demangler.Parse("_ZN4funcEPRPc"));
-  ASSERT_EQ("func(char**&)", demangler.Parse("_ZN4funcERRPPc"));
-  ASSERT_EQ("func(char const)", demangler.Parse("_ZN4funcEKc"));
-  ASSERT_EQ("func(char volatile)", demangler.Parse("_ZN4funcEVc"));
-  ASSERT_EQ("func(char volatile const)", demangler.Parse("_ZN4funcEKVc"));
-  ASSERT_EQ("func(char const volatile)", demangler.Parse("_ZN4funcEVKc"));
-  ASSERT_EQ("func(char const* volatile&)", demangler.Parse("_ZN4funcERVPKc"));
-  ASSERT_EQ("func(void, char, short)", demangler.Parse("_ZN4funcEvcs"));
-  ASSERT_EQ("func(void*, char&, short&*)", demangler.Parse("_ZN4funcEPvRcPRs"));
-}
-
-TEST(DemangleTest, FunctionModifiers) {
-  Demangler demangler;
-
-  ASSERT_EQ("func() const", demangler.Parse("_ZNK4funcEv"));
-  ASSERT_EQ("func() volatile", demangler.Parse("_ZNV4funcEv"));
-  ASSERT_EQ("func() volatile const", demangler.Parse("_ZNKV4funcEv"));
-  ASSERT_EQ("func() const volatile", demangler.Parse("_ZNVK4funcEv"));
-}
-
-TEST(DemangleTest, MultiplePartsInName) {
-  Demangler demangler;
-
-  ASSERT_EQ("one::two()", demangler.Parse("_ZN3one3twoEv"));
-  ASSERT_EQ("one::two::three()", demangler.Parse("_ZN3one3two5threeEv"));
-  ASSERT_EQ("one::two::three::four()", demangler.Parse("_ZN3one3two5three4fourEv"));
-  ASSERT_EQ("one::two::three::four::five()", demangler.Parse("_ZN3one3two5three4four4fiveEv"));
-  ASSERT_EQ("one(two::three::four::five)", demangler.Parse("_ZN3oneEN3two5three4four4fiveE"));
-}
-
-TEST(DemangleTest, AnonymousNamespace) {
-  Demangler demangler;
-
-  ASSERT_EQ("(anonymous namespace)::two()", demangler.Parse("_ZN12_GLOBAL__N_13twoEv"));
-  ASSERT_EQ("one::two((anonymous namespace))", demangler.Parse("_ZN3one3twoE12_GLOBAL__N_1"));
-}
-
-TEST(DemangleTest, DestructorValues) {
-  Demangler demangler;
-
-  ASSERT_EQ("one::two::~two()", demangler.Parse("_ZN3one3twoD0Ev"));
-  ASSERT_EQ("one::two::~two()", demangler.Parse("_ZN3one3twoD1Ev"));
-  ASSERT_EQ("one::two::~two()", demangler.Parse("_ZN3one3twoD2Ev"));
-  ASSERT_EQ("one::two::~two()", demangler.Parse("_ZN3one3twoD5Ev"));
-  ASSERT_EQ("one::two::three::~three()", demangler.Parse("_ZN3one3two5threeD0Ev"));
-
-  ASSERT_EQ("_ZN3one3twoD3Ev", demangler.Parse("_ZN3one3twoD3Ev"));
-  ASSERT_EQ("_ZN3one3twoD4Ev", demangler.Parse("_ZN3one3twoD4Ev"));
-  ASSERT_EQ("_ZN3one3twoD6Ev", demangler.Parse("_ZN3one3twoD6Ev"));
-  ASSERT_EQ("_ZN3one3twoD7Ev", demangler.Parse("_ZN3one3twoD7Ev"));
-  ASSERT_EQ("_ZN3one3twoD8Ev", demangler.Parse("_ZN3one3twoD8Ev"));
-  ASSERT_EQ("_ZN3one3twoD9Ev", demangler.Parse("_ZN3one3twoD9Ev"));
-
-  ASSERT_EQ("one::two<three::four>::~two()", demangler.Parse("_ZN3one3twoIN5three4fourEED2Ev"));
-}
-
-TEST(DemangleTest, ConstructorValues) {
-  Demangler demangler;
-
-  ASSERT_EQ("one::two::two()", demangler.Parse("_ZN3one3twoC1Ev"));
-  ASSERT_EQ("one::two::two()", demangler.Parse("_ZN3one3twoC2Ev"));
-  ASSERT_EQ("one::two::two()", demangler.Parse("_ZN3one3twoC3Ev"));
-  ASSERT_EQ("one::two::two()", demangler.Parse("_ZN3one3twoC5Ev"));
-  ASSERT_EQ("one::two::three::three()", demangler.Parse("_ZN3one3two5threeC1Ev"));
-
-  ASSERT_EQ("_ZN3one3twoC0Ev", demangler.Parse("_ZN3one3twoC0Ev"));
-  ASSERT_EQ("_ZN3one3twoC4Ev", demangler.Parse("_ZN3one3twoC4Ev"));
-  ASSERT_EQ("_ZN3one3twoC6Ev", demangler.Parse("_ZN3one3twoC6Ev"));
-  ASSERT_EQ("_ZN3one3twoC7Ev", demangler.Parse("_ZN3one3twoC7Ev"));
-  ASSERT_EQ("_ZN3one3twoC8Ev", demangler.Parse("_ZN3one3twoC8Ev"));
-  ASSERT_EQ("_ZN3one3twoC9Ev", demangler.Parse("_ZN3one3twoC9Ev"));
-
-  ASSERT_EQ("one::two<three::four>::two()", demangler.Parse("_ZN3one3twoIN5three4fourEEC1Ev"));
-}
-
-TEST(DemangleTest, OperatorValues) {
-  Demangler demangler;
-
-  ASSERT_EQ("operator&&()", demangler.Parse("_Zaav"));
-  ASSERT_EQ("operator&()", demangler.Parse("_Zadv"));
-  ASSERT_EQ("operator&()", demangler.Parse("_Zanv"));
-  ASSERT_EQ("operator&=()", demangler.Parse("_ZaNv"));
-  ASSERT_EQ("operator=()", demangler.Parse("_ZaSv"));
-  ASSERT_EQ("operator()()", demangler.Parse("_Zclv"));
-  ASSERT_EQ("operator,()", demangler.Parse("_Zcmv"));
-  ASSERT_EQ("operator~()", demangler.Parse("_Zcov"));
-  ASSERT_EQ("operator delete[]()", demangler.Parse("_Zdav"));
-  ASSERT_EQ("operator*()", demangler.Parse("_Zdev"));
-  ASSERT_EQ("operator delete()", demangler.Parse("_Zdlv"));
-  ASSERT_EQ("operator/()", demangler.Parse("_Zdvv"));
-  ASSERT_EQ("operator/=()", demangler.Parse("_ZdVv"));
-  ASSERT_EQ("operator^()", demangler.Parse("_Zeov"));
-  ASSERT_EQ("operator^=()", demangler.Parse("_ZeOv"));
-  ASSERT_EQ("operator==()", demangler.Parse("_Zeqv"));
-  ASSERT_EQ("operator>=()", demangler.Parse("_Zgev"));
-  ASSERT_EQ("operator>()", demangler.Parse("_Zgtv"));
-  ASSERT_EQ("operator[]()", demangler.Parse("_Zixv"));
-  ASSERT_EQ("operator<=()", demangler.Parse("_Zlev"));
-  ASSERT_EQ("operator<<()", demangler.Parse("_Zlsv"));
-  ASSERT_EQ("operator<<=()", demangler.Parse("_ZlSv"));
-  ASSERT_EQ("operator<()", demangler.Parse("_Zltv"));
-  ASSERT_EQ("operator-()", demangler.Parse("_Zmiv"));
-  ASSERT_EQ("operator-=()", demangler.Parse("_ZmIv"));
-  ASSERT_EQ("operator*()", demangler.Parse("_Zmlv"));
-  ASSERT_EQ("operator*=()", demangler.Parse("_ZmLv"));
-  ASSERT_EQ("operator--()", demangler.Parse("_Zmmv"));
-  ASSERT_EQ("operator new[]()", demangler.Parse("_Znav"));
-  ASSERT_EQ("operator!=()", demangler.Parse("_Znev"));
-  ASSERT_EQ("operator-()", demangler.Parse("_Zngv"));
-  ASSERT_EQ("operator!()", demangler.Parse("_Zntv"));
-  ASSERT_EQ("operator new()", demangler.Parse("_Znwv"));
-  ASSERT_EQ("operator||()", demangler.Parse("_Zoov"));
-  ASSERT_EQ("operator|()", demangler.Parse("_Zorv"));
-  ASSERT_EQ("operator|=()", demangler.Parse("_ZoRv"));
-  ASSERT_EQ("operator->*()", demangler.Parse("_Zpmv"));
-  ASSERT_EQ("operator+()", demangler.Parse("_Zplv"));
-  ASSERT_EQ("operator+=()", demangler.Parse("_ZpLv"));
-  ASSERT_EQ("operator++()", demangler.Parse("_Zppv"));
-  ASSERT_EQ("operator+()", demangler.Parse("_Zpsv"));
-  ASSERT_EQ("operator->()", demangler.Parse("_Zptv"));
-  ASSERT_EQ("operator?()", demangler.Parse("_Zquv"));
-  ASSERT_EQ("operator%()", demangler.Parse("_Zrmv"));
-  ASSERT_EQ("operator%=()", demangler.Parse("_ZrMv"));
-  ASSERT_EQ("operator>>()", demangler.Parse("_Zrsv"));
-  ASSERT_EQ("operator>>=()", demangler.Parse("_ZrSv"));
-
-  // Spot check using an operator as part of function name.
-  ASSERT_EQ("operator&&()", demangler.Parse("_ZNaaEv"));
-  ASSERT_EQ("operator++()", demangler.Parse("_ZNppEv"));
-  ASSERT_EQ("one::operator++()", demangler.Parse("_ZN3oneppEv"));
-
-  // Spot check using an operator in an argument name.
-  ASSERT_EQ("operator+(operator|=)", demangler.Parse("_ZNpsENoRE"));
-  ASSERT_EQ("operator==()", demangler.Parse("_Zeqv"));
-  ASSERT_EQ("one(arg1::operator|=, arg2::operator==)",
-            demangler.Parse("_ZN3oneEN4arg1oREN4arg2eqE"));
-}
-
-TEST(DemangleTest, FunctionStartsWithNumber) {
-  Demangler demangler;
-
-  ASSERT_EQ("value(char, int)", demangler.Parse("_Z5valueci"));
-  ASSERT_EQ("abcdefjklmn(signed char)", demangler.Parse("_Z11abcdefjklmna"));
-  ASSERT_EQ("value(one, signed char)", demangler.Parse("_Z5value3onea"));
-}
-
-TEST(DemangleTest, FunctionStartsWithLPlusNumber) {
-  Demangler demangler;
-
-  ASSERT_EQ("value(char, int)", demangler.Parse("_ZL5valueci"));
-  ASSERT_EQ("abcdefjklmn(signed char)", demangler.Parse("_ZL11abcdefjklmna"));
-  ASSERT_EQ("value(one, signed char)", demangler.Parse("_ZL5value3onea"));
-}
-
-TEST(DemangleTest, StdTypes) {
-  Demangler demangler;
-
-  ASSERT_EQ("std::one", demangler.Parse("_ZNSt3oneE"));
-  ASSERT_EQ("std::one(std::two)", demangler.Parse("_ZNSt3oneESt3two"));
-  ASSERT_EQ("std::std::one(std::two)", demangler.Parse("_ZNStSt3oneESt3two"));
-  ASSERT_EQ("std()", demangler.Parse("_ZNStEv"));
-  ASSERT_EQ("one::std::std::two::~two(one::std::std::two)",
-            demangler.Parse("_ZN3oneStSt3twoD0ES0_"));
-
-  ASSERT_EQ("std::allocator", demangler.Parse("_ZNSaE"));
-  ASSERT_EQ("std::basic_string", demangler.Parse("_ZNSbE"));
-  ASSERT_EQ("_ZNScE", demangler.Parse("_ZNScE"));
-  ASSERT_EQ("std::iostream", demangler.Parse("_ZNSdE"));
-  ASSERT_EQ("_ZNSeE", demangler.Parse("_ZNSeE"));
-  ASSERT_EQ("_ZNSfE", demangler.Parse("_ZNSfE"));
-  ASSERT_EQ("_ZNSgE", demangler.Parse("_ZNSgE"));
-  ASSERT_EQ("_ZNShE", demangler.Parse("_ZNShE"));
-  ASSERT_EQ("std::istream", demangler.Parse("_ZNSiE"));
-  ASSERT_EQ("_ZNSjE", demangler.Parse("_ZNSjE"));
-  ASSERT_EQ("_ZNSkE", demangler.Parse("_ZNSkE"));
-  ASSERT_EQ("_ZNSlE", demangler.Parse("_ZNSlE"));
-  ASSERT_EQ("_ZNSmE", demangler.Parse("_ZNSmE"));
-  ASSERT_EQ("_ZNSnE", demangler.Parse("_ZNSnE"));
-  ASSERT_EQ("std::ostream", demangler.Parse("_ZNSoE"));
-  ASSERT_EQ("_ZNSpE", demangler.Parse("_ZNSpE"));
-  ASSERT_EQ("_ZNSqE", demangler.Parse("_ZNSqE"));
-  ASSERT_EQ("_ZNSrE", demangler.Parse("_ZNSrE"));
-  ASSERT_EQ("std::string", demangler.Parse("_ZNSsE"));
-  ASSERT_EQ("_ZNSuE", demangler.Parse("_ZNSuE"));
-  ASSERT_EQ("_ZNSvE", demangler.Parse("_ZNSvE"));
-  ASSERT_EQ("_ZNSwE", demangler.Parse("_ZNSwE"));
-  ASSERT_EQ("_ZNSxE", demangler.Parse("_ZNSxE"));
-  ASSERT_EQ("_ZNSyE", demangler.Parse("_ZNSyE"));
-  ASSERT_EQ("_ZNSzE", demangler.Parse("_ZNSzE"));
-}
-
-TEST(DemangleTest, SingleLetterArguments) {
-  Demangler demangler;
-
-  ASSERT_EQ("func(signed char)", demangler.Parse("_ZN4funcEa"));
-  ASSERT_EQ("func(bool)", demangler.Parse("_ZN4funcEb"));
-  ASSERT_EQ("func(char)", demangler.Parse("_ZN4funcEc"));
-  ASSERT_EQ("func(double)", demangler.Parse("_ZN4funcEd"));
-  ASSERT_EQ("func(long double)", demangler.Parse("_ZN4funcEe"));
-  ASSERT_EQ("func(float)", demangler.Parse("_ZN4funcEf"));
-  ASSERT_EQ("func(__float128)", demangler.Parse("_ZN4funcEg"));
-  ASSERT_EQ("func(unsigned char)", demangler.Parse("_ZN4funcEh"));
-  ASSERT_EQ("func(int)", demangler.Parse("_ZN4funcEi"));
-  ASSERT_EQ("func(unsigned int)", demangler.Parse("_ZN4funcEj"));
-  ASSERT_EQ("_ZN4funcEk", demangler.Parse("_ZN4funcEk"));
-  ASSERT_EQ("func(long)", demangler.Parse("_ZN4funcEl"));
-  ASSERT_EQ("func(unsigned long)", demangler.Parse("_ZN4funcEm"));
-  ASSERT_EQ("func(__int128)", demangler.Parse("_ZN4funcEn"));
-  ASSERT_EQ("func(unsigned __int128)", demangler.Parse("_ZN4funcEo"));
-  ASSERT_EQ("_ZN4funcEp", demangler.Parse("_ZN4funcEp"));
-  ASSERT_EQ("_ZN4funcEq", demangler.Parse("_ZN4funcEq"));
-  ASSERT_EQ("_ZN4funcEr", demangler.Parse("_ZN4funcEr"));
-  ASSERT_EQ("func(short)", demangler.Parse("_ZN4funcEs"));
-  ASSERT_EQ("func(unsigned short)", demangler.Parse("_ZN4funcEt"));
-  ASSERT_EQ("_ZN4funcEu", demangler.Parse("_ZN4funcEu"));
-  ASSERT_EQ("func()", demangler.Parse("_ZN4funcEv"));
-  ASSERT_EQ("func(wchar_t)", demangler.Parse("_ZN4funcEw"));
-  ASSERT_EQ("func(long long)", demangler.Parse("_ZN4funcEx"));
-  ASSERT_EQ("func(unsigned long long)", demangler.Parse("_ZN4funcEy"));
-  ASSERT_EQ("func(...)", demangler.Parse("_ZN4funcEz"));
-}
-
-TEST(DemangleTest, DArguments) {
-  Demangler demangler;
-
-  ASSERT_EQ("func(auto)", demangler.Parse("_ZN4funcEDa"));
-  ASSERT_EQ("_ZN4funcEDb", demangler.Parse("_ZN4funcEDb"));
-  ASSERT_EQ("_ZN4funcEDc", demangler.Parse("_ZN4funcEDc"));
-  ASSERT_EQ("func(decimal64)", demangler.Parse("_ZN4funcEDd"));
-  ASSERT_EQ("func(decimal128)", demangler.Parse("_ZN4funcEDe"));
-  ASSERT_EQ("func(decimal32)", demangler.Parse("_ZN4funcEDf"));
-  ASSERT_EQ("_ZN4funcEDg", demangler.Parse("_ZN4funcEDg"));
-  ASSERT_EQ("func(half)", demangler.Parse("_ZN4funcEDh"));
-  ASSERT_EQ("func(char32_t)", demangler.Parse("_ZN4funcEDi"));
-  ASSERT_EQ("_ZN4funcEDj", demangler.Parse("_ZN4funcEDj"));
-  ASSERT_EQ("_ZN4funcEDk", demangler.Parse("_ZN4funcEDk"));
-  ASSERT_EQ("_ZN4funcEDl", demangler.Parse("_ZN4funcEDl"));
-  ASSERT_EQ("_ZN4funcEDm", demangler.Parse("_ZN4funcEDm"));
-  ASSERT_EQ("func(decltype(nullptr))", demangler.Parse("_ZN4funcEDn"));
-  ASSERT_EQ("_ZN4funcEDo", demangler.Parse("_ZN4funcEDo"));
-  ASSERT_EQ("_ZN4funcEDp", demangler.Parse("_ZN4funcEDp"));
-  ASSERT_EQ("_ZN4funcEDq", demangler.Parse("_ZN4funcEDq"));
-  ASSERT_EQ("_ZN4funcEDr", demangler.Parse("_ZN4funcEDr"));
-  ASSERT_EQ("func(char16_t)", demangler.Parse("_ZN4funcEDs"));
-  ASSERT_EQ("_ZN4funcEDt", demangler.Parse("_ZN4funcEDt"));
-  ASSERT_EQ("_ZN4funcEDu", demangler.Parse("_ZN4funcEDu"));
-  ASSERT_EQ("_ZN4funcEDv", demangler.Parse("_ZN4funcEDv"));
-  ASSERT_EQ("_ZN4funcEDw", demangler.Parse("_ZN4funcEDw"));
-  ASSERT_EQ("_ZN4funcEDx", demangler.Parse("_ZN4funcEDx"));
-  ASSERT_EQ("_ZN4funcEDy", demangler.Parse("_ZN4funcEDy"));
-  ASSERT_EQ("_ZN4funcEDz", demangler.Parse("_ZN4funcEDz"));
-}
-
-TEST(DemangleTest, FunctionArguments) {
-  Demangler demangler;
-
-  ASSERT_EQ("func(char ())", demangler.Parse("_ZN4funcEFcvE"));
-  ASSERT_EQ("func(char (*)())", demangler.Parse("_ZN4funcEPFcvE"));
-  ASSERT_EQ("func(char (&)())", demangler.Parse("_ZN4funcERFcvE"));
-  ASSERT_EQ("func(char (&)())", demangler.Parse("_ZN4funcERFcvE"));
-  ASSERT_EQ("func(char (*&)())", demangler.Parse("_ZN4funcERPFcvE"));
-  ASSERT_EQ("func(char (*)(int) const)", demangler.Parse("_ZN4funcEPKFciE"));
-  ASSERT_EQ("func(char (&)() const)", demangler.Parse("_ZN4funcERKFcvE"));
-  ASSERT_EQ("func(char (&)() volatile)", demangler.Parse("_ZN4funcERVFcvE"));
-  ASSERT_EQ("func(char (&)() volatile const)", demangler.Parse("_ZN4funcERKVFcvE"));
-  ASSERT_EQ("func(char (&)() const volatile)", demangler.Parse("_ZN4funcERVKFcvE"));
-  ASSERT_EQ("func(char (&)(int, signed char) const)", demangler.Parse("_ZN4funcERKFciaE"));
-  ASSERT_EQ("fake(char (&* volatile const)(void, void, signed char), signed char)",
-            demangler.Parse("_ZN4fakeEKVPRFcvvaEa"));
-}
-
-TEST(DemangleTest, TemplateFunction) {
-  Demangler demangler;
-
-  ASSERT_EQ("one<char>", demangler.Parse("_ZN3oneIcEE"));
-  ASSERT_EQ("one<void>", demangler.Parse("_ZN3oneIvEE"));
-  ASSERT_EQ("one<void*>", demangler.Parse("_ZN3oneIPvEE"));
-  ASSERT_EQ("one<void const>", demangler.Parse("_ZN3oneIKvEE"));
-  ASSERT_EQ("one<char, int, bool>", demangler.Parse("_ZN3oneIcibEE"));
-  ASSERT_EQ("one::two<three>", demangler.Parse("_ZN3one3twoIN5threeEEE"));
-  ASSERT_EQ("one<char, int, two::three>", demangler.Parse("_ZN3oneIciN3two5threeEEE"));
-  // Template within templates.
-  ASSERT_EQ("one::two<three<char, int>>", demangler.Parse("_ZN3one3twoIN5threeIciEEEE"));
-  ASSERT_EQ("one::two<three<char, four<int>>>", demangler.Parse("_ZN3one3twoIN5threeIcN4fourIiEEEEEE"));
-
-  ASSERT_EQ("one<char>", demangler.Parse("_Z3oneIcE"));
-  ASSERT_EQ("one<void>", demangler.Parse("_Z3oneIvE"));
-  ASSERT_EQ("one<void*>", demangler.Parse("_Z3oneIPvE"));
-  ASSERT_EQ("one<void const>", demangler.Parse("_Z3oneIKvE"));
-  ASSERT_EQ("one<char, int, bool>", demangler.Parse("_Z3oneIcibE"));
-  ASSERT_EQ("one(two<three>)", demangler.Parse("_Z3one3twoIN5threeEE"));
-  ASSERT_EQ("one<char, int, two::three>", demangler.Parse("_Z3oneIciN3two5threeEE"));
-  // Template within templates.
-  ASSERT_EQ("one(two<three<char, int>>)", demangler.Parse("_Z3one3twoIN5threeIciEEE"));
-  ASSERT_EQ("one(two<three<char, four<int>>>)",
-            demangler.Parse("_Z3one3twoIN5threeIcN4fourIiEEEEE"));
-}
-
-TEST(DemangleTest, TemplateFunctionWithReturnType) {
-  Demangler demangler;
-
-  ASSERT_EQ("char one<int>(char)", demangler.Parse("_Z3oneIiEcc"));
-  ASSERT_EQ("void one<int>()", demangler.Parse("_Z3oneIiEvv"));
-  ASSERT_EQ("char one<int>()", demangler.Parse("_Z3oneIiEcv"));
-  ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_Z3oneIiEcvv"));
-  ASSERT_EQ("char one<int>()", demangler.Parse("_ZN3oneIiEEcv"));
-  ASSERT_EQ("char one<int>(void, void)", demangler.Parse("_ZN3oneIiEEcvv"));
-}
-
-TEST(DemangleTest, TemplateArguments) {
-  Demangler demangler;
-
-  ASSERT_EQ("one(two<char>)", demangler.Parse("_ZN3oneE3twoIcE"));
-  ASSERT_EQ("one(two<char, void>)", demangler.Parse("_ZN3oneE3twoIcvE"));
-  ASSERT_EQ("one(two<char, void, three<four, int>>)",
-            demangler.Parse("_ZN3oneE3twoIcv5threeI4fouriEE"));
-}
-
-TEST(DemangleTest, SubstitutionUnderscore) {
-  Demangler demangler;
-
-  ASSERT_EQ("a::a", demangler.Parse("_ZN1aS_E"));
-  ASSERT_EQ("one::one", demangler.Parse("_ZN3oneS_E"));
-  ASSERT_EQ("one::two::one", demangler.Parse("_ZN3one3twoS_E"));
-  ASSERT_EQ("one::two::three::one", demangler.Parse("_ZN3one3two5threeS_E"));
-  ASSERT_EQ("one::two(one)", demangler.Parse("_ZN3one3twoES_"));
-  ASSERT_EQ("one::two(three::one)", demangler.Parse("_ZN3one3twoEN5threeS_E"));
-
-  // Special case that St is part of the saved value used in the substitution.
-  ASSERT_EQ("std::one::std::one", demangler.Parse("_ZNSt3oneS_E"));
-
-  // Multiple substitutions in the string.
-  ASSERT_EQ("one::one(one, one)", demangler.Parse("_ZN3oneS_ES_S_"));
-  ASSERT_EQ("std::one::two::std::one(std::one)", demangler.Parse("_ZNSt3one3twoS_ES_"));
-}
-
-TEST(DemangleTest, SubstitutionByNumber) {
-  Demangler demangler;
-
-  // Basic substitution.
-  ASSERT_EQ("a::b::c(a::b)", demangler.Parse("_ZN1a1b1cES0_"));
-  ASSERT_EQ("_ZN1a1b1cES1_", demangler.Parse("_ZN1a1b1cES1_"));
-  ASSERT_EQ("a::b::c::d(a::b::c)", demangler.Parse("_ZN1a1b1c1dES1_"));
-  ASSERT_EQ("a::b::c::d::e::f::g::h::i::j::k::l::m::n::o::p::q(a::b::c::d::e::f::g::h::i::j::k::l)",
-            demangler.Parse("_ZN1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1qESA_"));
-  ASSERT_EQ("a::b::c::d::e::f::g::h::i::j::k::l::m::n::o::p::q(a::b::c::d::e::f::g::h::i::j::k::l::m)",
-            demangler.Parse("_ZN1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1qESB_"));
-
-  // Verify argument modifiers are included in substitution list.
-  ASSERT_EQ("one::two(char&* volatile const, char&)", demangler.Parse("_ZN3one3twoEKVPRcS0_"));
-  ASSERT_EQ("one::two(char&* volatile const, char&*)", demangler.Parse("_ZN3one3twoEKVPRcS1_"));
-  ASSERT_EQ("one::two(char&* volatile const, char&* volatile const)",
-            demangler.Parse("_ZN3one3twoEKVPRcS2_"));
-  ASSERT_EQ("one::two(int&* volatile* const, int&)", demangler.Parse("_ZN3one3twoEKPVPRiS0_"));
-  ASSERT_EQ("one::two(int&* volatile const, int&*)", demangler.Parse("_ZN3one3twoEKVPRiS1_"));
-  ASSERT_EQ("one::two(int&* volatile const, int&* volatile const)",
-            demangler.Parse("_ZN3one3twoEKVPRiS2_"));
-
-  // Verify Constructor/Destructor does properly save from function name.
-  ASSERT_EQ("_ZN1a1bES0_", demangler.Parse("_ZN1a1bES0_"));
-  ASSERT_EQ("a::b::b(a::b)", demangler.Parse("_ZN1a1bC1ES0_"));
-  ASSERT_EQ("a::b::~b(a::b)", demangler.Parse("_ZN1a1bD0ES0_"));
-
-  // Make sure substitution values are not saved.
-  ASSERT_EQ("a::b::b(a::b, char*, char*)", demangler.Parse("_ZN1a1bC1ES0_PcS1_"));
-}
-
-TEST(DemangleTest, ComplexSubstitution) {
-  Demangler demangler;
-
-  ASSERT_EQ("one::two<one::three>::two()", demangler.Parse("_ZN3one3twoINS_5threeEEC1Ev"));
-  ASSERT_EQ("one::two::two(one::two const&, bool, one::three*)",
-            demangler.Parse("_ZN3one3twoC2ERKS0_bPNS_5threeE"));
-  ASSERT_EQ("one::two::three::four<one::five>::~four(one::two*)",
-            demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS0_"));
-  ASSERT_EQ("one::two::three::four<one::five>::~four(one::two::three*)",
-            demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS1_"));
-  ASSERT_EQ("one::two::three::four<one::five>::~four(one::two::three::four*)",
-            demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS2_"));
-  ASSERT_EQ("one::two::three::four<one::five>::~four(one::five*)",
-            demangler.Parse("_ZN3one3two5three4fourINS_4fiveEED2EPS3_"));
-}
-
-TEST(DemangleTest, TemplateSubstitution) {
-  Demangler demangler;
-
-  ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_ZN3oneIidEEvT_"));
-  ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_ZN3oneIidEEvT0_"));
-  ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_ZN3oneIidcvEEvT1_"));
-
-  ASSERT_EQ("void one<int, double>(int)", demangler.Parse("_Z3oneIidEvT_"));
-  ASSERT_EQ("void one<int, double>(double)", demangler.Parse("_Z3oneIidEvT0_"));
-  ASSERT_EQ("void one<int, double, char, void>(char)", demangler.Parse("_Z3oneIidcvEvT1_"));
-
-  ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)",
-            demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT10_"));
-  ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)",
-            demangler.Parse("_ZN3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEEvT11_"));
-
-  ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(l)",
-            demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT10_"));
-  ASSERT_EQ("void one<a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r>(m)",
-            demangler.Parse("_Z3oneI1a1b1c1d1e1f1g1h1i1j1k1l1m1n1o1p1q1rEvT11_"));
-}
-
-TEST(DemangleTest, StringTooLong) {
-  Demangler demangler;
-
-  ASSERT_EQ("_ZN3one3twoC2ERKS0_bPNS_5threeE",
-            demangler.Parse("_ZN3one3twoC2ERKS0_bPNS_5threeE", 10));
-  ASSERT_EQ("_ZN3one3twoC2ERKS0_bPNS_5threeE",
-            demangler.Parse("_ZN3one3twoC2ERKS0_bPNS_5threeE", 30));
-  ASSERT_EQ("one::two::two(one::two const&, bool, one::three*)",
-            demangler.Parse("_ZN3one3twoC2ERKS0_bPNS_5threeE", 31));
-
-  // Check the length check only occurs after the two letter value
-  // has been processed.
-  ASSERT_EQ("one::two(auto)", demangler.Parse("_ZN3one3twoEDa", 15));
-  ASSERT_EQ("one::two(auto)", demangler.Parse("_ZN3one3twoEDa", 14));
-  ASSERT_EQ("one::two(auto)", demangler.Parse("_ZN3one3twoEDa", 13));
-  ASSERT_EQ("_ZN3one3twoEDa", demangler.Parse("_ZN3one3twoEDa", 12));
-}
-
-TEST(DemangleTest, BooleanLiterals) {
-  Demangler demangler;
-
-  ASSERT_EQ("one<true>", demangler.Parse("_ZN3oneILb1EEE"));
-  ASSERT_EQ("one<false>", demangler.Parse("_ZN3oneILb0EEE"));
-  ASSERT_EQ("one<false, true>", demangler.Parse("_ZN3oneILb0ELb1EEE"));
-
-  ASSERT_EQ("one<true>", demangler.Parse("_Z3oneILb1EE"));
-  ASSERT_EQ("one<false>", demangler.Parse("_Z3oneILb0EE"));
-  ASSERT_EQ("one<false, true>", demangler.Parse("_Z3oneILb0ELb1EE"));
-
-  ASSERT_EQ("one(two<three<four>, false, true>)",
-            demangler.Parse("_ZN3oneE3twoI5threeI4fourELb0ELb1EE"));
-}
-
-TEST(DemangleTest, non_virtual_thunk) {
-  Demangler demangler;
-
-  ASSERT_EQ("non-virtual thunk to one", demangler.Parse("_ZThn0_N3oneE"));
-  ASSERT_EQ("non-virtual thunk to two", demangler.Parse("_ZThn0_3two"));
-  ASSERT_EQ("non-virtual thunk to three", demangler.Parse("_ZTh0_5three"));
-  ASSERT_EQ("non-virtual thunk to four", demangler.Parse("_ZTh_4four"));
-  ASSERT_EQ("non-virtual thunk to five", demangler.Parse("_ZTh0123456789_4five"));
-  ASSERT_EQ("non-virtual thunk to six", demangler.Parse("_ZThn0123456789_3six"));
-
-  ASSERT_EQ("_ZThn0N3oneE", demangler.Parse("_ZThn0N3oneE"));
-  ASSERT_EQ("_ZThn03two", demangler.Parse("_ZThn03two"));
-  ASSERT_EQ("_ZTh05three", demangler.Parse("_ZTh05three"));
-  ASSERT_EQ("_ZTh4four", demangler.Parse("_ZTh4four"));
-  ASSERT_EQ("_ZTh01234567894five", demangler.Parse("_ZTh01234567894five"));
-  ASSERT_EQ("_ZThn01234567893six", demangler.Parse("_ZThn01234567893six"));
-  ASSERT_EQ("_ZT_N3oneE", demangler.Parse("_ZT_N3oneE"));
-  ASSERT_EQ("_ZT0_N3oneE", demangler.Parse("_ZT0_N3oneE"));
-  ASSERT_EQ("_ZTH_N3oneE", demangler.Parse("_ZTH_N3oneE"));
-}
-
-TEST(DemangleTest, r_value_reference) {
-  Demangler demangler;
-  ASSERT_EQ(
-      "android::SurfaceComposerClient::Transaction::merge(android::SurfaceComposerClient::"
-      "Transaction&&)",
-      demangler.Parse("_ZN7android21SurfaceComposerClient11Transaction5mergeEOS1_"));
-}
-
-TEST(DemangleTest, initial_St) {
-  Demangler demangler;
-  EXPECT_EQ("std::state", demangler.Parse("_ZSt5state"));
-  EXPECT_EQ("std::_In::ward", demangler.Parse("_ZNSt3_In4wardE"));
-  EXPECT_EQ("std::__terminate(void (*)())", demangler.Parse("_ZSt11__terminatePFvvE"));
-}
-
-TEST(DemangleTest, cfi) {
-  Demangler demangler;
-  EXPECT_EQ("nfa_sys_ptim_timer_update(tPTIM_CB*)",
-            demangler.Parse("_Z25nfa_sys_ptim_timer_updateP8tPTIM_CB"));
-  EXPECT_EQ("nfa_sys_ptim_timer_update(tPTIM_CB*) [clone .cfi]",
-            demangler.Parse("_Z25nfa_sys_ptim_timer_updateP8tPTIM_CB.cfi"));
-}
-
-TEST(DemangleTest, demangle) {
-  std::string str;
-
-  str = demangle("_ZN1a1b1cES0_");
-  ASSERT_EQ("a::b::c(a::b)", str);
-
-  str = demangle("_");
-  ASSERT_EQ("_", str);
-
-  str = demangle("_Z");
-  ASSERT_EQ("_Z", str);
-
-  str = demangle("_Za");
-  ASSERT_EQ("_Za", str);
-
-  str = demangle("_Zaa");
-  ASSERT_EQ("operator&&", str);
-
-  str = demangle("Xa");
-  ASSERT_EQ("Xa", str);
-}
diff --git a/demangle/Demangler.cpp b/demangle/Demangler.cpp
deleted file mode 100644
index 7a3aa81..0000000
--- a/demangle/Demangler.cpp
+++ /dev/null
@@ -1,924 +0,0 @@
-/*
- * Copyright (C) 2017 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 <assert.h>
-
-#include <cctype>
-#include <stack>
-#include <string>
-#include <vector>
-
-#include "Demangler.h"
-
-constexpr const char* Demangler::kTypes[];
-constexpr const char* Demangler::kDTypes[];
-constexpr const char* Demangler::kSTypes[];
-
-void Demangler::Save(const std::string& str, bool is_name) {
-  saves_.push_back(str);
-  last_save_name_ = is_name;
-}
-
-std::string Demangler::GetArgumentsString() {
-  size_t num_args = cur_state_.args.size();
-  std::string arg_str;
-  if (num_args > 0) {
-    arg_str = cur_state_.args[0];
-    for (size_t i = 1; i < num_args; i++) {
-      arg_str += ", " + cur_state_.args[i];
-    }
-  }
-  return arg_str;
-}
-
-const char* Demangler::AppendOperatorString(const char* name) {
-  const char* oper = nullptr;
-  switch (*name) {
-  case 'a':
-    name++;
-    switch (*name) {
-    case 'a':
-      oper = "operator&&";
-      break;
-    case 'd':
-    case 'n':
-      oper = "operator&";
-      break;
-    case 'N':
-      oper = "operator&=";
-      break;
-    case 'S':
-      oper = "operator=";
-      break;
-    }
-    break;
-  case 'c':
-    name++;
-    switch (*name) {
-    case 'l':
-      oper = "operator()";
-      break;
-    case 'm':
-      oper = "operator,";
-      break;
-    case 'o':
-      oper = "operator~";
-      break;
-    }
-    break;
-  case 'd':
-    name++;
-    switch (*name) {
-    case 'a':
-      oper = "operator delete[]";
-      break;
-    case 'e':
-      oper = "operator*";
-      break;
-    case 'l':
-      oper = "operator delete";
-      break;
-    case 'v':
-      oper = "operator/";
-      break;
-    case 'V':
-      oper = "operator/=";
-      break;
-    }
-    break;
-  case 'e':
-    name++;
-    switch (*name) {
-    case 'o':
-      oper = "operator^";
-      break;
-    case 'O':
-      oper = "operator^=";
-      break;
-    case 'q':
-      oper = "operator==";
-      break;
-    }
-    break;
-  case 'g':
-    name++;
-    switch (*name) {
-    case 'e':
-      oper = "operator>=";
-      break;
-    case 't':
-      oper = "operator>";
-      break;
-    }
-    break;
-  case 'i':
-    name++;
-    switch (*name) {
-    case 'x':
-      oper = "operator[]";
-      break;
-    }
-    break;
-  case 'l':
-    name++;
-    switch (*name) {
-    case 'e':
-      oper = "operator<=";
-      break;
-    case 's':
-      oper = "operator<<";
-      break;
-    case 'S':
-      oper = "operator<<=";
-      break;
-    case 't':
-      oper = "operator<";
-      break;
-    }
-    break;
-  case 'm':
-    name++;
-    switch (*name) {
-    case 'i':
-      oper = "operator-";
-      break;
-    case 'I':
-      oper = "operator-=";
-      break;
-    case 'l':
-      oper = "operator*";
-      break;
-    case 'L':
-      oper = "operator*=";
-      break;
-    case 'm':
-      oper = "operator--";
-      break;
-    }
-    break;
-  case 'n':
-    name++;
-    switch (*name) {
-    case 'a':
-      oper = "operator new[]";
-      break;
-    case 'e':
-      oper = "operator!=";
-      break;
-    case 'g':
-      oper = "operator-";
-      break;
-    case 't':
-      oper = "operator!";
-      break;
-    case 'w':
-      oper = "operator new";
-      break;
-    }
-    break;
-  case 'o':
-    name++;
-    switch (*name) {
-    case 'o':
-      oper = "operator||";
-      break;
-    case 'r':
-      oper = "operator|";
-      break;
-    case 'R':
-      oper = "operator|=";
-      break;
-    }
-    break;
-  case 'p':
-    name++;
-    switch (*name) {
-    case 'm':
-      oper = "operator->*";
-      break;
-    case 'l':
-      oper = "operator+";
-      break;
-    case 'L':
-      oper = "operator+=";
-      break;
-    case 'p':
-      oper = "operator++";
-      break;
-    case 's':
-      oper = "operator+";
-      break;
-    case 't':
-      oper = "operator->";
-      break;
-    }
-    break;
-  case 'q':
-    name++;
-    switch (*name) {
-    case 'u':
-      oper = "operator?";
-      break;
-    }
-    break;
-  case 'r':
-    name++;
-    switch (*name) {
-    case 'm':
-      oper = "operator%";
-      break;
-    case 'M':
-      oper = "operator%=";
-      break;
-    case 's':
-      oper = "operator>>";
-      break;
-    case 'S':
-      oper = "operator>>=";
-      break;
-    }
-    break;
-  }
-  if (oper == nullptr) {
-    return nullptr;
-  }
-  AppendCurrent(oper);
-  cur_state_.last_save = oper;
-  return name + 1;
-}
-
-const char* Demangler::GetStringFromLength(const char* name, std::string* str) {
-  assert(std::isdigit(*name));
-
-  size_t length = *name - '0';
-  name++;
-  while (*name != '\0' && std::isdigit(*name)) {
-    length = length * 10 + *name - '0';
-    name++;
-  }
-
-  std::string read_str;
-  while (*name != '\0' && length != 0) {
-    read_str += *name;
-    name++;
-    length--;
-  }
-  if (length != 0) {
-    return nullptr;
-  }
-  // Special replacement of _GLOBAL__N_1 to (anonymous namespace).
-  if (read_str == "_GLOBAL__N_1") {
-    *str += "(anonymous namespace)";
-  } else {
-    *str += read_str;
-  }
-  return name;
-}
-
-void Demangler::AppendCurrent(const std::string& str) {
-  if (!cur_state_.str.empty()) {
-    cur_state_.str += "::";
-  }
-  cur_state_.str += str;
-}
-
-void Demangler::AppendCurrent(const char* str) {
-  if (!cur_state_.str.empty()) {
-    cur_state_.str += "::";
-  }
-  cur_state_.str += str;
-}
-
-const char* Demangler::ParseS(const char* name) {
-  if (std::islower(*name)) {
-    const char* type = kSTypes[*name - 'a'];
-    if (type == nullptr) {
-      return nullptr;
-    }
-    AppendCurrent(type);
-    return name + 1;
-  }
-
-  if (saves_.empty()) {
-    return nullptr;
-  }
-
-  if (*name == '_') {
-    last_save_name_ = false;
-    AppendCurrent(saves_[0]);
-    return name + 1;
-  }
-
-  bool isdigit = std::isdigit(*name);
-  if (!isdigit && !std::isupper(*name)) {
-    return nullptr;
-  }
-
-  size_t index;
-  if (isdigit) {
-    index = *name - '0' + 1;
-  } else {
-    index = *name - 'A' + 11;
-  }
-  name++;
-  if (*name != '_') {
-    return nullptr;
-  }
-
-  if (index >= saves_.size()) {
-    return nullptr;
-  }
-
-  last_save_name_ = false;
-  AppendCurrent(saves_[index]);
-  return name + 1;
-}
-
-const char* Demangler::ParseT(const char* name) {
-  if (template_saves_.empty()) {
-    return nullptr;
-  }
-
-  if (*name == '_') {
-    last_save_name_ = false;
-    AppendCurrent(template_saves_[0]);
-    return name + 1;
-  }
-
-  // Need to get the total number.
-  char* end;
-  unsigned long int index = strtoul(name, &end, 10) + 1;
-  if (name == end || *end != '_') {
-    return nullptr;
-  }
-
-  if (index >= template_saves_.size()) {
-    return nullptr;
-  }
-
-  last_save_name_ = false;
-  AppendCurrent(template_saves_[index]);
-  return end + 1;
-}
-
-const char* Demangler::ParseFunctionName(const char* name) {
-  if (*name == 'E') {
-    if (parse_funcs_.empty()) {
-      return nullptr;
-    }
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-
-    // Remove the last saved part so that the full function name is not saved.
-    // But only if the last save was not something like a substitution.
-    if (!saves_.empty() && last_save_name_) {
-      saves_.pop_back();
-    }
-
-    function_name_ += cur_state_.str;
-    while (!cur_state_.suffixes.empty()) {
-      function_suffix_ += cur_state_.suffixes.back();
-      cur_state_.suffixes.pop_back();
-    }
-    cur_state_.Clear();
-
-    return name + 1;
-  }
-
-  if (*name == 'I') {
-    state_stack_.push(cur_state_);
-    cur_state_.Clear();
-
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseFunctionNameTemplate;
-    return name + 1;
-  }
-
-  return ParseComplexString(name);
-}
-
-const char* Demangler::ParseFunctionNameTemplate(const char* name) {
-  if (*name == 'E' && name[1] == 'E') {
-    // Only consider this a template with saves if it is right before
-    // the end of the name.
-    template_found_ = true;
-    template_saves_ = cur_state_.args;
-  }
-  return ParseTemplateArgumentsComplex(name);
-}
-
-const char* Demangler::ParseComplexArgument(const char* name) {
-  if (*name == 'E') {
-    if (parse_funcs_.empty()) {
-      return nullptr;
-    }
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-
-    AppendArgument(cur_state_.str);
-    cur_state_.str.clear();
-
-    return name + 1;
-  }
-
-  return ParseComplexString(name);
-}
-
-void Demangler::FinalizeTemplate() {
-  std::string arg_str(GetArgumentsString());
-  cur_state_ = state_stack_.top();
-  state_stack_.pop();
-  cur_state_.str += '<' + arg_str + '>';
-}
-
-const char* Demangler::ParseComplexString(const char* name) {
-  if (*name == 'S') {
-    name++;
-    if (*name == 't') {
-      AppendCurrent("std");
-      return name + 1;
-    }
-    return ParseS(name);
-  }
-  if (*name == 'L') {
-    name++;
-    if (!std::isdigit(*name)) {
-      return nullptr;
-    }
-  }
-  if (std::isdigit(*name)) {
-    std::string str;
-    name = GetStringFromLength(name, &str);
-    if (name == nullptr) {
-      return name;
-    }
-    AppendCurrent(str);
-    Save(cur_state_.str, true);
-    cur_state_.last_save = std::move(str);
-    return name;
-  }
-  if (*name == 'D') {
-    name++;
-    if (saves_.empty() || (*name != '0' && *name != '1' && *name != '2'
-        && *name != '5')) {
-      return nullptr;
-    }
-    last_save_name_ = false;
-    AppendCurrent("~" + cur_state_.last_save);
-    return name + 1;
-  }
-  if (*name == 'C') {
-    name++;
-    if (saves_.empty() || (*name != '1' && *name != '2' && *name != '3'
-        && *name != '5')) {
-      return nullptr;
-    }
-    last_save_name_ = false;
-    AppendCurrent(cur_state_.last_save);
-    return name + 1;
-  }
-  if (*name == 'K') {
-    cur_state_.suffixes.push_back(" const");
-    return name + 1;
-  }
-  if (*name == 'V') {
-    cur_state_.suffixes.push_back(" volatile");
-    return name + 1;
-  }
-  if (*name == 'I') {
-    // Save the current argument state.
-    state_stack_.push(cur_state_);
-    cur_state_.Clear();
-
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseTemplateArgumentsComplex;
-    return name + 1;
-  }
-  name = AppendOperatorString(name);
-  if (name != nullptr) {
-    Save(cur_state_.str, true);
-  }
-  return name;
-}
-
-void Demangler::AppendArgument(const std::string& str) {
-  std::string arg(str);
-  while (!cur_state_.suffixes.empty()) {
-    arg += cur_state_.suffixes.back();
-    cur_state_.suffixes.pop_back();
-    Save(arg, false);
-  }
-  cur_state_.args.push_back(arg);
-}
-
-const char* Demangler::ParseFunctionArgument(const char* name) {
-  if (*name == 'E') {
-    // The first argument is the function modifier.
-    // The second argument is the function type.
-    // The third argument is the return type of the function.
-    // The rest of the arguments are the function arguments.
-    size_t num_args = cur_state_.args.size();
-    if (num_args < 4) {
-      return nullptr;
-    }
-    std::string function_modifier = cur_state_.args[0];
-    std::string function_type = cur_state_.args[1];
-
-    std::string str = cur_state_.args[2] + ' ';
-    if (!cur_state_.args[1].empty()) {
-      str += '(' + cur_state_.args[1] + ')';
-    }
-
-    if (num_args == 4 && cur_state_.args[3] == "void") {
-      str += "()";
-    } else {
-      str += '(' + cur_state_.args[3];
-      for (size_t i = 4; i < num_args; i++) {
-        str += ", " + cur_state_.args[i];
-      }
-      str += ')';
-    }
-    str += cur_state_.args[0];
-
-    cur_state_ = state_stack_.top();
-    state_stack_.pop();
-    cur_state_.args.emplace_back(std::move(str));
-
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-    return name + 1;
-  }
-  return ParseArguments(name);
-}
-
-const char* Demangler::ParseArguments(const char* name) {
-  switch (*name) {
-  case 'P':
-    cur_state_.suffixes.push_back("*");
-    return name + 1;
-
-  case 'R':
-    // This should always be okay because the string is guaranteed to have
-    // at least two characters before this. A mangled string always starts
-    // with _Z.
-    if (name[-1] != 'R') {
-      // Multiple 'R's in a row only add a single &.
-      cur_state_.suffixes.push_back("&");
-    }
-    return name + 1;
-
-  case 'O':
-    cur_state_.suffixes.push_back("&&");
-    return name + 1;
-
-  case 'K':
-  case 'V': {
-    const char* suffix;
-    if (*name == 'K') {
-      suffix = " const";
-    } else {
-      suffix = " volatile";
-    }
-    if (!cur_state_.suffixes.empty() && (name[-1] == 'K' || name[-1] == 'V')) {
-      // Special case, const/volatile apply as a single entity.
-      size_t index = cur_state_.suffixes.size();
-      cur_state_.suffixes[index-1].insert(0, suffix);
-    } else {
-      cur_state_.suffixes.push_back(suffix);
-    }
-    return name + 1;
-  }
-
-  case 'F': {
-    std::string function_modifier;
-    std::string function_type;
-    if (!cur_state_.suffixes.empty()) {
-      // If the first element starts with a ' ', then this modifies the
-      // function itself.
-      if (cur_state_.suffixes.back()[0] == ' ') {
-        function_modifier = cur_state_.suffixes.back();
-        cur_state_.suffixes.pop_back();
-      }
-      while (!cur_state_.suffixes.empty()) {
-        function_type += cur_state_.suffixes.back();
-        cur_state_.suffixes.pop_back();
-      }
-    }
-
-    state_stack_.push(cur_state_);
-
-    cur_state_.Clear();
-
-    // The function parameter has this format:
-    //   First argument is the function modifier.
-    //   Second argument is the function type.
-    //   Third argument will be the return function type but has not
-    //     been parsed yet.
-    //   Any other parameters are the arguments to the function. There
-    //     must be at least one or this isn't valid.
-    cur_state_.args.push_back(function_modifier);
-    cur_state_.args.push_back(function_type);
-
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseFunctionArgument;
-    return name + 1;
-  }
-
-  case 'N':
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseComplexArgument;
-    return name + 1;
-
-  case 'S':
-    name++;
-    if (*name == 't') {
-      cur_state_.str = "std::";
-      return name + 1;
-    }
-    name = ParseS(name);
-    if (name == nullptr) {
-      return nullptr;
-    }
-    AppendArgument(cur_state_.str);
-    cur_state_.str.clear();
-    return name;
-
-  case 'D':
-    name++;
-    if (*name >= 'a' && *name <= 'z') {
-      const char* arg = Demangler::kDTypes[*name - 'a'];
-      if (arg == nullptr) {
-        return nullptr;
-      }
-      AppendArgument(arg);
-      return name + 1;
-    }
-    return nullptr;
-
-  case 'I':
-    // Save the current argument state.
-    state_stack_.push(cur_state_);
-    cur_state_.Clear();
-
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseTemplateArguments;
-    return name + 1;
-
-  case 'v':
-    AppendArgument("void");
-    return name + 1;
-
-  default:
-    if (*name >= 'a' && *name <= 'z') {
-      const char* arg = Demangler::kTypes[*name - 'a'];
-      if (arg == nullptr) {
-        return nullptr;
-      }
-      AppendArgument(arg);
-      return name + 1;
-    } else if (std::isdigit(*name)) {
-      std::string arg = cur_state_.str;
-      name = GetStringFromLength(name, &arg);
-      if (name == nullptr) {
-        return nullptr;
-      }
-      Save(arg, true);
-      if (*name == 'I') {
-        // There is one case where this argument is not complete, and that's
-        // where this is a template argument.
-        cur_state_.str = arg;
-      } else {
-        AppendArgument(arg);
-        cur_state_.str.clear();
-      }
-      return name;
-    } else if (strcmp(name, ".cfi") == 0) {
-      function_suffix_ += " [clone .cfi]";
-      return name + 4;
-    }
-  }
-  return nullptr;
-}
-
-const char* Demangler::ParseTemplateLiteral(const char* name) {
-  if (*name == 'E') {
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-    return name + 1;
-  }
-  // Only understand boolean values with 0 or 1.
-  if (*name == 'b') {
-    name++;
-    if (*name == '0') {
-      AppendArgument("false");
-      cur_state_.str.clear();
-    } else if (*name == '1') {
-      AppendArgument("true");
-      cur_state_.str.clear();
-    } else {
-      return nullptr;
-    }
-    return name + 1;
-  }
-  return nullptr;
-}
-
-const char* Demangler::ParseTemplateArgumentsComplex(const char* name) {
-  if (*name == 'E') {
-    if (parse_funcs_.empty()) {
-      return nullptr;
-    }
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-
-    FinalizeTemplate();
-    Save(cur_state_.str, false);
-    return name + 1;
-  } else if (*name == 'L') {
-    // Literal value for a template.
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseTemplateLiteral;
-    return name + 1;
-  }
-
-  return ParseArguments(name);
-}
-
-const char* Demangler::ParseTemplateArguments(const char* name) {
-  if (*name == 'E') {
-    if (parse_funcs_.empty()) {
-      return nullptr;
-    }
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-    FinalizeTemplate();
-    AppendArgument(cur_state_.str);
-    cur_state_.str.clear();
-    return name + 1;
-  } else if (*name == 'L') {
-    // Literal value for a template.
-    parse_funcs_.push_back(parse_func_);
-    parse_func_ = &Demangler::ParseTemplateLiteral;
-    return name + 1;
-  }
-
-  return ParseArguments(name);
-}
-
-const char* Demangler::ParseFunctionTemplateArguments(const char* name) {
-  if (*name == 'E') {
-    parse_func_ = parse_funcs_.back();
-    parse_funcs_.pop_back();
-
-    function_name_ += '<' + GetArgumentsString() + '>';
-    template_found_ = true;
-    template_saves_ = cur_state_.args;
-    cur_state_.Clear();
-    return name + 1;
-  }
-  return ParseTemplateArgumentsComplex(name);
-}
-
-const char* Demangler::FindFunctionName(const char* name) {
-  if (*name == 'T') {
-    // non-virtual thunk, verify that it matches one of these patterns:
-    //   Thn[0-9]+_
-    //   Th[0-9]+_
-    //   Thn_
-    //   Th_
-    name++;
-    if (*name != 'h') {
-      return nullptr;
-    }
-    name++;
-    if (*name == 'n') {
-      name++;
-    }
-    while (std::isdigit(*name)) {
-      name++;
-    }
-    if (*name != '_') {
-      return nullptr;
-    }
-    function_name_ = "non-virtual thunk to ";
-    return name + 1;
-  }
-
-  if (*name == 'N') {
-    parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
-    parse_func_ = &Demangler::ParseFunctionName;
-    return name + 1;
-  }
-
-  if (*name == 'S') {
-    name++;
-    if (*name == 't') {
-      function_name_ = "std::";
-      name++;
-    } else {
-      return nullptr;
-    }
-  }
-
-  if (std::isdigit(*name)) {
-    name = GetStringFromLength(name, &function_name_);
-  } else if (*name == 'L' && std::isdigit(name[1])) {
-    name = GetStringFromLength(name + 1, &function_name_);
-  } else {
-    name = AppendOperatorString(name);
-    function_name_ = cur_state_.str;
-  }
-  cur_state_.Clear();
-
-  // Check for a template argument, which will still be part of the function
-  // name.
-  if (name != nullptr && *name == 'I') {
-    parse_funcs_.push_back(&Demangler::ParseArgumentsAtTopLevel);
-    parse_func_ = &Demangler::ParseFunctionTemplateArguments;
-    return name + 1;
-  }
-  parse_func_ = &Demangler::ParseArgumentsAtTopLevel;
-  return name;
-}
-
-const char* Demangler::ParseArgumentsAtTopLevel(const char* name) {
-  // At the top level is the only place where T is allowed.
-  if (*name == 'T') {
-    name++;
-    name = ParseT(name);
-    if (name == nullptr) {
-      return nullptr;
-    }
-    AppendArgument(cur_state_.str);
-    cur_state_.str.clear();
-    return name;
-  }
-
-  return Demangler::ParseArguments(name);
-}
-
-std::string Demangler::Parse(const char* name, size_t max_length) {
-  if (name[0] == '\0' || name[0] != '_' || name[1] == '\0' || name[1] != 'Z') {
-    // Name is not mangled.
-    return name;
-  }
-
-  Clear();
-
-  parse_func_ = &Demangler::FindFunctionName;
-  parse_funcs_.push_back(&Demangler::Fail);
-  const char* cur_name = name + 2;
-  while (cur_name != nullptr && *cur_name != '\0'
-      && static_cast<size_t>(cur_name - name) < max_length) {
-    cur_name = (this->*parse_func_)(cur_name);
-  }
-  if (cur_name == nullptr || *cur_name != '\0' || function_name_.empty() ||
-      !cur_state_.suffixes.empty()) {
-    return name;
-  }
-
-  std::string return_type;
-  if (template_found_) {
-    // Only a single argument with a template is not allowed.
-    if (cur_state_.args.size() == 1) {
-      return name;
-    }
-
-    // If there are at least two arguments, this template has a return type.
-    if (cur_state_.args.size() > 1) {
-      // The first argument will be the return value.
-      return_type = cur_state_.args[0] + ' ';
-      cur_state_.args.erase(cur_state_.args.begin());
-    }
-  }
-
-  std::string arg_str;
-  if (cur_state_.args.size() == 1 && cur_state_.args[0] == "void") {
-    // If the only argument is void, then don't print any args.
-    arg_str = "()";
-  } else {
-    arg_str = GetArgumentsString();
-    if (!arg_str.empty()) {
-      arg_str = '(' + arg_str + ')';
-    }
-  }
-  return return_type + function_name_ + arg_str + function_suffix_;
-}
-
-std::string demangle(const char* name) {
-  Demangler demangler;
-  return demangler.Parse(name);
-}
diff --git a/demangle/Demangler.h b/demangle/Demangler.h
deleted file mode 100644
index 3b7d44e..0000000
--- a/demangle/Demangler.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2017 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 __LIB_DEMANGLE_DEMANGLER_H
-#define __LIB_DEMANGLE_DEMANGLER_H
-
-#include <assert.h>
-
-#include <stack>
-#include <string>
-#include <vector>
-
-class Demangler {
- public:
-  Demangler() = default;
-
-  // NOTE: The max_length is not guaranteed to be the absolute max length
-  // of a string that will be rejected. Under certain circumstances the
-  // length check will not occur until after the second letter of a pair
-  // is checked.
-  std::string Parse(const char* name, size_t max_length = kMaxDefaultLength);
-
-  void AppendCurrent(const std::string& str);
-  void AppendCurrent(const char* str);
-  void AppendArgument(const std::string& str);
-  std::string GetArgumentsString();
-  void FinalizeTemplate();
-  const char* ParseS(const char* name);
-  const char* ParseT(const char* name);
-  const char* AppendOperatorString(const char* name);
-  void Save(const std::string& str, bool is_name);
-
- private:
-  void Clear() {
-    parse_funcs_.clear();
-    function_name_.clear();
-    function_suffix_.clear();
-    first_save_.clear();
-    cur_state_.Clear();
-    saves_.clear();
-    template_saves_.clear();
-    while (!state_stack_.empty()) {
-      state_stack_.pop();
-    }
-    last_save_name_ = false;
-    template_found_ = false;
-  }
-
-  using parse_func_type = const char* (Demangler::*)(const char*);
-  parse_func_type parse_func_;
-  std::vector<parse_func_type> parse_funcs_;
-  std::vector<std::string> saves_;
-  std::vector<std::string> template_saves_;
-  bool last_save_name_;
-  bool template_found_;
-
-  std::string function_name_;
-  std::string function_suffix_;
-
-  struct StateData {
-    void Clear() {
-      str.clear();
-      args.clear();
-      prefix.clear();
-      suffixes.clear();
-      last_save.clear();
-    }
-
-    std::string str;
-    std::vector<std::string> args;
-    std::string prefix;
-    std::vector<std::string> suffixes;
-    std::string last_save;
-  };
-  std::stack<StateData> state_stack_;
-  std::string first_save_;
-  StateData cur_state_;
-
-  static const char* GetStringFromLength(const char* name, std::string* str);
-
-  // Parsing functions.
-  const char* ParseComplexString(const char* name);
-  const char* ParseComplexArgument(const char* name);
-  const char* ParseArgumentsAtTopLevel(const char* name);
-  const char* ParseArguments(const char* name);
-  const char* ParseTemplateArguments(const char* name);
-  const char* ParseTemplateArgumentsComplex(const char* name);
-  const char* ParseTemplateLiteral(const char* name);
-  const char* ParseFunctionArgument(const char* name);
-  const char* ParseFunctionName(const char* name);
-  const char* ParseFunctionNameTemplate(const char* name);
-  const char* ParseFunctionTemplateArguments(const char* name);
-  const char* FindFunctionName(const char* name);
-  const char* Fail(const char*) { return nullptr; }
-
-  // The default maximum string length string to process.
-  static constexpr size_t kMaxDefaultLength = 2048;
-
-  static constexpr const char* kTypes[] = {
-    "signed char",        // a
-    "bool",               // b
-    "char",               // c
-    "double",             // d
-    "long double",        // e
-    "float",              // f
-    "__float128",         // g
-    "unsigned char",      // h
-    "int",                // i
-    "unsigned int",       // j
-    nullptr,              // k
-    "long",               // l
-    "unsigned long",      // m
-    "__int128",           // n
-    "unsigned __int128",  // o
-    nullptr,              // p
-    nullptr,              // q
-    nullptr,              // r
-    "short",              // s
-    "unsigned short",     // t
-    nullptr,              // u
-    "void",               // v
-    "wchar_t",            // w
-    "long long",          // x
-    "unsigned long long", // y
-    "...",                // z
-  };
-
-  static constexpr const char* kDTypes[] = {
-    "auto",               // a
-    nullptr,              // b
-    nullptr,              // c
-    "decimal64",          // d
-    "decimal128",         // e
-    "decimal32",          // f
-    nullptr,              // g
-    "half",               // h
-    "char32_t",           // i
-    nullptr,              // j
-    nullptr,              // k
-    nullptr,              // l
-    nullptr,              // m
-    "decltype(nullptr)",  // n
-    nullptr,              // o
-    nullptr,              // p
-    nullptr,              // q
-    nullptr,              // r
-    "char16_t",           // s
-    nullptr,              // t
-    nullptr,              // u
-    nullptr,              // v
-    nullptr,              // w
-    nullptr,              // x
-    nullptr,              // y
-    nullptr,              // z
-  };
-
-  static constexpr const char* kSTypes[] = {
-    "std::allocator",     // a
-    "std::basic_string",  // b
-    nullptr,              // c
-    "std::iostream",      // d
-    nullptr,              // e
-    nullptr,              // f
-    nullptr,              // g
-    nullptr,              // h
-    "std::istream",       // i
-    nullptr,              // j
-    nullptr,              // k
-    nullptr,              // l
-    nullptr,              // m
-    nullptr,              // n
-    "std::ostream",       // o
-    nullptr,              // p
-    nullptr,              // q
-    nullptr,              // r
-    "std::string",        // s
-    nullptr,              // t
-    nullptr,              // u
-    nullptr,              // v
-    nullptr,              // w
-    nullptr,              // x
-    nullptr,              // y
-    nullptr,              // z
-  };
-};
-
-#endif  // __LIB_DEMANGLE_DEMANGLER_H
diff --git a/demangle/OWNERS b/demangle/OWNERS
deleted file mode 100644
index 6f7e4a3..0000000
--- a/demangle/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-cferris@google.com
diff --git a/demangle/demangle.cpp b/demangle/demangle.cpp
deleted file mode 100644
index 66e5e58..0000000
--- a/demangle/demangle.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2017 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 <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cctype>
-#include <string>
-
-#include <demangle.h>
-
-extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
-
-static void Usage(const char* prog_name) {
-  printf("usage: %s [-c] [NAME_TO_DEMANGLE...]\n", prog_name);
-  printf("\n");
-  printf("Demangles C++ mangled names if supplied on the command-line, or found\n");
-  printf("reading from stdin otherwise.\n");
-  printf("\n");
-  printf("-c\tCompare against __cxa_demangle\n");
-  printf("\n");
-}
-
-static std::string DemangleWithCxa(const char* name) {
-  const char* cxa_demangle = __cxa_demangle(name, nullptr, nullptr, nullptr);
-  if (cxa_demangle == nullptr) {
-    return name;
-  }
-
-  // The format of our demangler is slightly different from the cxa demangler
-  // so modify the cxa demangler output. Specifically, for templates, remove
-  // the spaces between '>' and '>'.
-  std::string demangled_str;
-  for (size_t i = 0; i < strlen(cxa_demangle); i++) {
-    if (i > 2 && cxa_demangle[i] == '>' && std::isspace(cxa_demangle[i - 1]) &&
-        cxa_demangle[i - 2] == '>') {
-      demangled_str.resize(demangled_str.size() - 1);
-    }
-    demangled_str += cxa_demangle[i];
-  }
-  return demangled_str;
-}
-
-static void Compare(const char* name, const std::string& demangled_name) {
-  std::string cxa_demangled_name(DemangleWithCxa(name));
-  if (cxa_demangled_name != demangled_name) {
-    printf("\nMismatch!\n");
-    printf("\tmangled name: %s\n", name);
-    printf("\tour demangle: %s\n", demangled_name.c_str());
-    printf("\tcxa demangle: %s\n", cxa_demangled_name.c_str());
-    exit(1);
-  }
-}
-
-static int Filter(bool compare) {
-  char* line = nullptr;
-  size_t line_length = 0;
-
-  while ((getline(&line, &line_length, stdin)) != -1) {
-    char* p = line;
-    char* name;
-    while ((name = strstr(p, "_Z")) != nullptr) {
-      // Output anything before the identifier.
-      *name = 0;
-      printf("%s", p);
-      *name = '_';
-
-      // Extract the identifier.
-      p = name;
-      while (*p && (std::isalnum(*p) || *p == '_' || *p == '.' || *p == '$')) ++p;
-
-      // Demangle and output.
-      std::string identifier(name, p);
-      std::string demangled_name = demangle(identifier.c_str());
-      printf("%s", demangled_name.c_str());
-
-      if (compare) Compare(identifier.c_str(), demangled_name);
-    }
-    // Output anything after the last identifier.
-    printf("%s", p);
-  }
-
-  free(line);
-  return 0;
-}
-
-int main(int argc, char** argv) {
-#ifdef __BIONIC__
-  const char* prog_name = getprogname();
-#else
-  const char* prog_name = argv[0];
-#endif
-
-  bool compare = false;
-  int opt_char;
-  while ((opt_char = getopt(argc, argv, "c")) != -1) {
-    if (opt_char == 'c') {
-      compare = true;
-    } else {
-      Usage(prog_name);
-      return 1;
-    }
-  }
-
-  // With no arguments, act as a filter.
-  if (optind == argc) return Filter(compare);
-
-  // Otherwise demangle each argument.
-  while (optind < argc) {
-    const char* name = argv[optind++];
-    std::string demangled_name = demangle(name);
-    printf("%s\n", demangled_name.c_str());
-
-    if (compare) Compare(name, demangled_name);
-  }
-  return 0;
-}
diff --git a/demangle/demangle_fuzzer.cpp b/demangle/demangle_fuzzer.cpp
deleted file mode 100644
index 83fafc2..0000000
--- a/demangle/demangle_fuzzer.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <string>
-
-#include "Demangler.h"
-
-extern "C" void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  std::vector<char> data_str(size + 1);
-  memcpy(data_str.data(), data, size);
-  data_str[size] = '\0';
-
-  Demangler demangler;
-  std::string demangled_name = demangler.Parse(data_str.data());
-  if (size != 0 && data_str[0] != '\0' && demangled_name.empty()) {
-    abort();
-  }
-}
diff --git a/demangle/include/demangle.h b/demangle/include/demangle.h
deleted file mode 100644
index 01f1b80..0000000
--- a/demangle/include/demangle.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 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 __LIB_DEMANGLE_H_
-#define __LIB_DEMANGLE_H_
-
-#include <string>
-
-// If the name cannot be demangled, the original name will be returned as
-// a std::string. If the name can be demangled, then the demangled name
-// will be returned as a std::string.
-std::string demangle(const char* name);
-
-#endif  // __LIB_DEMANGLE_H_
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 716fe95..a757d56 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -122,6 +122,7 @@
 
     shared_libs: [
         "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
         "android.hardware.fastboot@1.0",
         "android.hardware.health@2.0",
         "libadbd",
@@ -134,17 +135,21 @@
         "libfs_mgr",
         "libgsi",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "liblp",
+        "libprotobuf-cpp-lite",
         "libsparse",
         "libutils",
     ],
 
     static_libs: [
         "libhealthhalutils",
+        "libsnapshot_nobinder",
     ],
+
+    header_libs: [
+        "libsnapshot_headers",
+    ]
 }
 
 cc_defaults {
@@ -187,7 +192,11 @@
     // will violate ODR.
     shared_libs: [],
 
-    header_libs: ["bootimg_headers"],
+    header_libs: [
+        "avb_headers",
+        "bootimg_headers",
+    ],
+
     static_libs: [
         "libziparchive",
         "libsparse",
diff --git a/fastboot/constants.h b/fastboot/constants.h
index 8a72627..5a554a0 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -34,6 +34,7 @@
 #define FB_CMD_UPDATE_SUPER "update-super"
 #define FB_CMD_OEM "oem"
 #define FB_CMD_GSI "gsi"
+#define FB_CMD_SNAPSHOT_UPDATE "snapshot-update"
 
 #define RESPONSE_OKAY "OKAY"
 #define RESPONSE_FAIL "FAIL"
@@ -66,3 +67,5 @@
 #define FB_VAR_BATTERY_VOLTAGE "battery-voltage"
 #define FB_VAR_BATTERY_SOC_OK "battery-soc-ok"
 #define FB_VAR_SUPER_PARTITION_NAME "super-partition-name"
+#define FB_VAR_SNAPSHOT_UPDATE_STATUS "snapshot-update-status"
+#define FB_VAR_CPU_ABI "cpu-abi"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 1b09f79..1a745ab 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -19,12 +19,15 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include <unordered_set>
+
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
 #include <cutils/android_reboot.h>
 #include <ext4_utils/wipe.h>
 #include <fs_mgr.h>
@@ -32,6 +35,7 @@
 #include <libgsi/libgsi.h>
 #include <liblp/builder.h>
 #include <liblp/liblp.h>
+#include <libsnapshot/snapshot.h>
 #include <uuid/uuid.h>
 
 #include "constants.h"
@@ -39,14 +43,16 @@
 #include "flashing.h"
 #include "utility.h"
 
+using android::fs_mgr::MetadataBuilder;
 using ::android::hardware::hidl_string;
 using ::android::hardware::boot::V1_0::BoolResult;
 using ::android::hardware::boot::V1_0::CommandResult;
 using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::boot::V1_1::MergeStatus;
 using ::android::hardware::fastboot::V1_0::Result;
 using ::android::hardware::fastboot::V1_0::Status;
-
-using namespace android::fs_mgr;
+using android::snapshot::SnapshotManager;
+using IBootControl1_1 = ::android::hardware::boot::V1_1::IBootControl;
 
 struct VariableHandlers {
     // Callback to retrieve the value of a single variable.
@@ -55,6 +61,24 @@
     std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args;
 };
 
+static bool IsSnapshotUpdateInProgress(FastbootDevice* device) {
+    auto hal = device->boot1_1();
+    if (!hal) {
+        return false;
+    }
+    auto merge_status = hal->getSnapshotMergeStatus();
+    return merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING;
+}
+
+static bool IsProtectedPartitionDuringMerge(FastbootDevice* device, const std::string& name) {
+    static const std::unordered_set<std::string> ProtectedPartitionsDuringMerge = {
+            "userdata", "metadata", "misc"};
+    if (ProtectedPartitionsDuringMerge.count(name) == 0) {
+        return false;
+    }
+    return IsSnapshotUpdateInProgress(device);
+}
+
 static void GetAllVars(FastbootDevice* device, const std::string& name,
                        const VariableHandlers& handlers) {
     if (!handlers.get_all_args) {
@@ -102,7 +126,9 @@
             {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
             {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
             {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}},
-            {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}}};
+            {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}},
+            {FB_VAR_SNAPSHOT_UPDATE_STATUS, {GetSnapshotUpdateStatus, nullptr}},
+            {FB_VAR_CPU_ABI, {GetCpuAbi, nullptr}}};
 
     if (args.size() < 2) {
         return device->WriteFail("Missing argument");
@@ -139,8 +165,14 @@
         return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices");
     }
 
+    const auto& partition_name = args[1];
+    if (IsProtectedPartitionDuringMerge(device, partition_name)) {
+        auto message = "Cannot erase " + partition_name + " while a snapshot update is in progress";
+        return device->WriteFail(message);
+    }
+
     PartitionHandle handle;
-    if (!OpenPartition(device, args[1], &handle)) {
+    if (!OpenPartition(device, partition_name, &handle)) {
         return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
     }
     if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) {
@@ -195,23 +227,6 @@
     return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
 }
 
-bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
-    if (args.size() < 2) {
-        return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
-    }
-
-    if (GetDeviceLockStatus()) {
-        return device->WriteStatus(FastbootResult::FAIL,
-                                   "Flashing is not allowed on locked devices");
-    }
-
-    int ret = Flash(device, args[1]);
-    if (ret < 0) {
-        return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
-    }
-    return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
-}
-
 bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
     if (args.size() < 2) {
         return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
@@ -222,9 +237,9 @@
                                    "set_active command is not allowed on locked devices");
     }
 
-    // Slot suffix needs to be between 'a' and 'z'.
     Slot slot;
     if (!GetSlotNumber(args[1], &slot)) {
+        // Slot suffix needs to be between 'a' and 'z'.
         return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix");
     }
 
@@ -237,6 +252,32 @@
     if (slot >= boot_control_hal->getNumberSlots()) {
         return device->WriteStatus(FastbootResult::FAIL, "Slot out of range");
     }
+
+    // If the slot is not changing, do nothing.
+    if (slot == boot_control_hal->getCurrentSlot()) {
+        return device->WriteOkay("");
+    }
+
+    // Check how to handle the current snapshot state.
+    if (auto hal11 = device->boot1_1()) {
+        auto merge_status = hal11->getSnapshotMergeStatus();
+        if (merge_status == MergeStatus::MERGING) {
+            return device->WriteFail("Cannot change slots while a snapshot update is in progress");
+        }
+        // Note: we allow the slot change if the state is SNAPSHOTTED. First-
+        // stage init does not have access to the HAL, and uses the slot number
+        // and /metadata OTA state to determine whether a slot change occurred.
+        // Booting into the old slot would erase the OTA, and switching A->B->A
+        // would simply resume it if no boots occur in between. Re-flashing
+        // partitions implicitly cancels the OTA, so leaving the state as-is is
+        // safe.
+        if (merge_status == MergeStatus::SNAPSHOTTED) {
+            device->WriteInfo(
+                    "Changing the active slot with a snapshot applied may cancel the"
+                    " update.");
+        }
+    }
+
     CommandResult ret;
     auto cb = [&ret](CommandResult result) { ret = result; };
     auto result = boot_control_hal->setActiveBootSlot(slot, cb);
@@ -340,7 +381,7 @@
 PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name)
     : device_(device) {
     std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
-    slot_number_ = SlotNumberForSlotSuffix(slot_suffix);
+    slot_number_ = android::fs_mgr::SlotNumberForSlotSuffix(slot_suffix);
     auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number_));
     if (!super_device) {
         return;
@@ -350,7 +391,7 @@
 }
 
 bool PartitionBuilder::Write() {
-    std::unique_ptr<LpMetadata> metadata = builder_->Export();
+    auto metadata = builder_->Export();
     if (!metadata) {
         return false;
     }
@@ -381,7 +422,7 @@
         return device->WriteFail("Partition already exists");
     }
 
-    Partition* partition = builder->AddPartition(partition_name, 0);
+    auto partition = builder->AddPartition(partition_name, 0);
     if (!partition) {
         return device->WriteFail("Failed to add partition");
     }
@@ -437,10 +478,15 @@
         return device->WriteFail("Could not open super partition");
     }
 
-    Partition* partition = builder->FindPartition(partition_name);
+    auto partition = builder->FindPartition(partition_name);
     if (!partition) {
         return device->WriteFail("Partition does not exist");
     }
+
+    // Remove the updated flag to cancel any snapshots.
+    uint32_t attrs = partition->attributes();
+    partition->set_attributes(attrs & ~LP_PARTITION_ATTR_UPDATED);
+
     if (!builder->ResizePartition(partition, partition_size)) {
         return device->WriteFail("Not enough space to resize partition");
     }
@@ -450,6 +496,47 @@
     return device->WriteOkay("Partition resized");
 }
 
+void CancelPartitionSnapshot(FastbootDevice* device, const std::string& partition_name) {
+    PartitionBuilder builder(device, partition_name);
+    if (!builder.Valid()) return;
+
+    auto partition = builder->FindPartition(partition_name);
+    if (!partition) return;
+
+    // Remove the updated flag to cancel any snapshots.
+    uint32_t attrs = partition->attributes();
+    partition->set_attributes(attrs & ~LP_PARTITION_ATTR_UPDATED);
+
+    builder.Write();
+}
+
+bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
+    if (args.size() < 2) {
+        return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
+    }
+
+    if (GetDeviceLockStatus()) {
+        return device->WriteStatus(FastbootResult::FAIL,
+                                   "Flashing is not allowed on locked devices");
+    }
+
+    const auto& partition_name = args[1];
+    if (IsProtectedPartitionDuringMerge(device, partition_name)) {
+        auto message = "Cannot flash " + partition_name + " while a snapshot update is in progress";
+        return device->WriteFail(message);
+    }
+
+    if (LogicalPartitionExists(device, partition_name)) {
+        CancelPartitionSnapshot(device, partition_name);
+    }
+
+    int ret = Flash(device, partition_name);
+    if (ret < 0) {
+        return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
+    }
+    return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
+}
+
 bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
     if (args.size() < 2) {
         return device->WriteFail("Invalid arguments");
@@ -466,7 +553,7 @@
 class AutoMountMetadata {
   public:
     AutoMountMetadata() {
-        Fstab proc_mounts;
+        android::fs_mgr::Fstab proc_mounts;
         if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
             LOG(ERROR) << "Could not read /proc/mounts";
             return;
@@ -494,7 +581,7 @@
     explicit operator bool() const { return mounted_; }
 
   private:
-    Fstab fstab_;
+    android::fs_mgr::Fstab fstab_;
     bool mounted_ = false;
     bool should_unmount_ = false;
 };
@@ -524,3 +611,53 @@
     }
     return device->WriteStatus(FastbootResult::OKAY, "Success");
 }
+
+bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string>& args) {
+    // Note that we use the HAL rather than mounting /metadata, since we want
+    // our results to match the bootloader.
+    auto hal = device->boot1_1();
+    if (!hal) return device->WriteFail("Not supported");
+
+    // If no arguments, return the same thing as a getvar. Note that we get the
+    // HAL first so we can return "not supported" before we return the less
+    // specific error message below.
+    if (args.size() < 2 || args[1].empty()) {
+        std::string message;
+        if (!GetSnapshotUpdateStatus(device, {}, &message)) {
+            return device->WriteFail("Could not determine update status");
+        }
+        device->WriteInfo(message);
+        return device->WriteOkay("");
+    }
+
+    MergeStatus status = hal->getSnapshotMergeStatus();
+
+    if (args.size() != 2) {
+        return device->WriteFail("Invalid arguments");
+    }
+    if (args[1] == "cancel") {
+        switch (status) {
+            case MergeStatus::SNAPSHOTTED:
+            case MergeStatus::MERGING:
+                hal->setSnapshotMergeStatus(MergeStatus::CANCELLED);
+                break;
+            default:
+                break;
+        }
+    } else if (args[1] == "merge") {
+        if (status != MergeStatus::MERGING) {
+            return device->WriteFail("No snapshot merge is in progress");
+        }
+
+        auto sm = SnapshotManager::NewForFirstStageMount();
+        if (!sm) {
+            return device->WriteFail("Unable to create SnapshotManager");
+        }
+        if (!sm->HandleImminentDataWipe()) {
+            return device->WriteFail("Unable to finish snapshot merge");
+        }
+    } else {
+        return device->WriteFail("Invalid parameter to snapshot-update");
+    }
+    return device->WriteStatus(FastbootResult::OKAY, "Success");
+}
diff --git a/fastboot/device/commands.h b/fastboot/device/commands.h
index afd6d08..c1324bc 100644
--- a/fastboot/device/commands.h
+++ b/fastboot/device/commands.h
@@ -19,7 +19,7 @@
 #include <string>
 #include <vector>
 
-constexpr unsigned int kMaxDownloadSizeDefault = 0x20000000;
+constexpr unsigned int kMaxDownloadSizeDefault = 0x10000000;
 
 class FastbootDevice;
 
@@ -49,3 +49,4 @@
 bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args);
 bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args);
 bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args);
+bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string>& args);
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 56fafab..31fc359 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -54,12 +54,17 @@
               {FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
               {FB_CMD_OEM, OemCmdHandler},
               {FB_CMD_GSI, GsiHandler},
+              {FB_CMD_SNAPSHOT_UPDATE, SnapshotUpdateHandler},
       }),
       transport_(std::make_unique<ClientUsbTransport>()),
       boot_control_hal_(IBootControl::getService()),
       health_hal_(get_health_service()),
       fastboot_hal_(IFastboot::getService()),
-      active_slot_("") {}
+      active_slot_("") {
+    if (boot_control_hal_) {
+        boot1_1_ = android::hardware::boot::V1_1::IBootControl::castFrom(boot_control_hal_);
+    }
+}
 
 FastbootDevice::~FastbootDevice() {
     CloseDevice();
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index 091aadf..bbe8172 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include <android/hardware/boot/1.0/IBootControl.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
 #include <android/hardware/fastboot/1.0/IFastboot.h>
 #include <android/hardware/health/2.0/IHealth.h>
 
@@ -51,6 +52,7 @@
     android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal() {
         return boot_control_hal_;
     }
+    android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1() { return boot1_1_; }
     android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal() {
         return fastboot_hal_;
     }
@@ -63,6 +65,7 @@
 
     std::unique_ptr<Transport> transport_;
     android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_;
+    android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1_;
     android::sp<android::hardware::health::V2_0::IHealth> health_hal_;
     android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal_;
     std::vector<char> download_data_;
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index 99854c9..102ebdb 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -32,6 +32,7 @@
 #include <fstab/fstab.h>
 #include <liblp/builder.h>
 #include <liblp/liblp.h>
+#include <libsnapshot/snapshot.h>
 #include <sparse/sparse.h>
 
 #include "fastboot_device.h"
@@ -171,6 +172,11 @@
         if (!slot_suffix.empty() && GetPartitionSlotSuffix(partition_name) == slot_suffix) {
             continue;
         }
+        std::string group_name = GetPartitionGroupName(old_metadata->groups[partition.group_index]);
+        // Skip partitions in the COW group
+        if (group_name == android::snapshot::kCowGroupName) {
+            continue;
+        }
         partitions_to_keep.emplace(partition_name);
     }
 
diff --git a/fastboot/device/usb_client.cpp b/fastboot/device/usb_client.cpp
index 1014291..5066046 100644
--- a/fastboot/device/usb_client.cpp
+++ b/fastboot/device/usb_client.cpp
@@ -258,7 +258,7 @@
         auto bytes_read_now =
                 handle_->read(handle_.get(), char_data, bytes_to_read, true /* allow_partial */);
         if (bytes_read_now < 0) {
-            return bytes_read_total;
+            return bytes_read_total == 0 ? -1 : bytes_read_total;
         }
         bytes_read_total += bytes_read_now;
         char_data += bytes_read_now;
@@ -279,7 +279,7 @@
         auto bytes_to_write = std::min(len - bytes_written_total, kFbFfsNumBufs * kFbFfsBufSize);
         auto bytes_written_now = handle_->write(handle_.get(), data, bytes_to_write);
         if (bytes_written_now < 0) {
-            return bytes_written_total;
+            return bytes_written_total == 0 ? -1 : bytes_written_total;
         }
         bytes_written_total += bytes_written_now;
         char_data += bytes_written_now;
diff --git a/fastboot/device/utility.cpp b/fastboot/device/utility.cpp
index 2ebd57d..b3f2d5f 100644
--- a/fastboot/device/utility.cpp
+++ b/fastboot/device/utility.cpp
@@ -56,12 +56,20 @@
     if (!path) {
         return false;
     }
+
+    CreateLogicalPartitionParams params = {
+            .block_device = *path,
+            .metadata_slot = slot_number,
+            .partition_name = partition_name,
+            .force_writable = true,
+            .timeout_ms = 5s,
+    };
     std::string dm_path;
-    if (!CreateLogicalPartition(path->c_str(), slot_number, partition_name, true, 5s, &dm_path)) {
+    if (!CreateLogicalPartition(params, &dm_path)) {
         LOG(ERROR) << "Could not map partition: " << partition_name;
         return false;
     }
-    auto closer = [partition_name]() -> void { DestroyLogicalPartition(partition_name, 5s); };
+    auto closer = [partition_name]() -> void { DestroyLogicalPartition(partition_name); };
     *handle = PartitionHandle(dm_path, std::move(closer));
     return true;
 }
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index 130a3cf..10eac01 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -23,6 +23,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
 #include <ext4_utils/ext4_utils.h>
 #include <fs_mgr.h>
 #include <healthhalutils/HealthHalUtils.h>
@@ -34,9 +35,11 @@
 
 using ::android::hardware::boot::V1_0::BoolResult;
 using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::boot::V1_1::MergeStatus;
 using ::android::hardware::fastboot::V1_0::FileSystemType;
 using ::android::hardware::fastboot::V1_0::Result;
 using ::android::hardware::fastboot::V1_0::Status;
+using IBootControl1_1 = ::android::hardware::boot::V1_1::IBootControl;
 using namespace android::fs_mgr;
 
 constexpr char kFastbootProtocolVersion[] = "0.4";
@@ -424,3 +427,34 @@
     *message = fs_mgr_get_super_partition_name(slot_number);
     return true;
 }
+
+bool GetSnapshotUpdateStatus(FastbootDevice* device, const std::vector<std::string>& /* args */,
+                             std::string* message) {
+    // Note that we use the HAL rather than mounting /metadata, since we want
+    // our results to match the bootloader.
+    auto hal = device->boot1_1();
+    if (!hal) {
+        *message = "not supported";
+        return false;
+    }
+
+    MergeStatus status = hal->getSnapshotMergeStatus();
+    switch (status) {
+        case MergeStatus::SNAPSHOTTED:
+            *message = "snapshotted";
+            break;
+        case MergeStatus::MERGING:
+            *message = "merging";
+            break;
+        default:
+            *message = "none";
+            break;
+    }
+    return true;
+}
+
+bool GetCpuAbi(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+               std::string* message) {
+    *message = android::base::GetProperty("ro.product.cpu.abi", "");
+    return true;
+}
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index 015a4c5..90840d6 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -61,6 +61,9 @@
                      std::string* message);
 bool GetSuperPartitionName(FastbootDevice* device, const std::vector<std::string>& args,
                            std::string* message);
+bool GetSnapshotUpdateStatus(FastbootDevice* device, const std::vector<std::string>& args,
+                             std::string* message);
+bool GetCpuAbi(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
 
 // Helpers for getvar all.
 std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c8caa67..7fdc28b 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -51,6 +51,7 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/endian.h>
 #include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
@@ -59,6 +60,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <build/version.h>
+#include <libavb/libavb.h>
 #include <liblp/liblp.h>
 #include <platform_tools_version.h>
 #include <sparse/sparse.h>
@@ -144,14 +146,13 @@
     { "dts",      "dt.img",           "dt.sig",       "dts",      true,  ImageType::BootCritical },
     { "odm",      "odm.img",          "odm.sig",      "odm",      true,  ImageType::Normal },
     { "product",  "product.img",      "product.sig",  "product",  true,  ImageType::Normal },
-    { "product_services",
-                  "product_services.img",
-                                      "product_services.sig",
-                                                      "product_services",
-                                                                  true,  ImageType::Normal },
     { "recovery", "recovery.img",     "recovery.sig", "recovery", true,  ImageType::BootCritical },
     { "super",    "super.img",        "super.sig",    "super",    true,  ImageType::Extra },
     { "system",   "system.img",       "system.sig",   "system",   false, ImageType::Normal },
+    { "system_ext",
+                  "system_ext.img",   "system_ext.sig",
+                                                      "system_ext",
+                                                                  true,  ImageType::Normal },
     { nullptr,    "system_other.img", "system.sig",   "system",   true,  ImageType::Normal },
     { "userdata", "userdata.img",     "userdata.sig", "userdata", true,  ImageType::Extra },
     { "vbmeta",   "vbmeta.img",       "vbmeta.sig",   "vbmeta",   true,  ImageType::BootCritical },
@@ -161,6 +162,10 @@
                                                       "vbmeta_system",
                                                                   true,  ImageType::BootCritical },
     { "vendor",   "vendor.img",       "vendor.sig",   "vendor",   true,  ImageType::Normal },
+    { "vendor_boot",
+                  "vendor_boot.img",  "vendor_boot.sig",
+                                                      "vendor_boot",
+                                                                  true,  ImageType::BootCritical },
     { nullptr,    "vendor_other.img", "vendor.sig",   "vendor",   true,  ImageType::Normal },
         // clang-format on
 };
@@ -389,6 +394,14 @@
             " set_active SLOT            Set the active slot.\n"
             " oem [COMMAND...]           Execute OEM-specific command.\n"
             " gsi wipe|disable           Wipe or disable a GSI installation (fastbootd only).\n"
+            " wipe-super [SUPER_EMPTY]   Wipe the super partition. This will reset it to\n"
+            "                            contain an empty set of default dynamic partitions.\n"
+            " snapshot-update cancel     On devices that support snapshot-based updates, cancel\n"
+            "                            an in-progress update. This may make the device\n"
+            "                            unbootable until it is reflashed.\n"
+            " snapshot-update merge      On devices that support snapshot-based updates, finish\n"
+            "                            an in-progress update if it is in the \"merging\"\n"
+            "                            phase.\n"
             "\n"
             "boot image:\n"
             " boot KERNEL [RAMDISK [SECOND]]\n"
@@ -502,9 +515,8 @@
 
 static bool UnzipToMemory(ZipArchiveHandle zip, const std::string& entry_name,
                           std::vector<char>* out) {
-    ZipString zip_entry_name(entry_name.c_str());
     ZipEntry zip_entry;
-    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
+    if (FindEntry(zip, entry_name, &zip_entry) != 0) {
         fprintf(stderr, "archive does not contain '%s'\n", entry_name.c_str());
         return false;
     }
@@ -614,9 +626,8 @@
 static int unzip_to_file(ZipArchiveHandle zip, const char* entry_name) {
     unique_fd fd(make_temporary_fd(entry_name));
 
-    ZipString zip_entry_name(entry_name);
     ZipEntry zip_entry;
-    if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) {
+    if (FindEntry(zip, entry_name, &zip_entry) != 0) {
         fprintf(stderr, "archive does not contain '%s'\n", entry_name);
         errno = ENOENT;
         return -1;
@@ -871,7 +882,7 @@
         return false;
     }
 
-    if (sparse_file* s = sparse_file_import_auto(fd, false, false)) {
+    if (sparse_file* s = sparse_file_import(fd, false, false)) {
         buf->image_size = sparse_file_len(s, false, false);
         sparse_file_destroy(s);
     } else {
@@ -916,33 +927,50 @@
     return load_buf_fd(fd.release(), buf);
 }
 
-static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf) {
+static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_boot) {
     // Buffer needs to be at least the size of the VBMeta struct which
     // is 256 bytes.
     if (buf->sz < 256) {
         return;
     }
 
-    int fd = make_temporary_fd("vbmeta rewriting");
-
     std::string data;
     if (!android::base::ReadFdToString(buf->fd, &data)) {
         die("Failed reading from vbmeta");
     }
 
+    uint64_t vbmeta_offset = 0;
+    if (vbmeta_in_boot) {
+        // Tries to locate top-level vbmeta from boot.img footer.
+        uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
+        if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
+            die("Failed to find AVB_FOOTER at offset: %" PRId64, footer_offset);
+        }
+        const AvbFooter* footer = reinterpret_cast<const AvbFooter*>(data.c_str() + footer_offset);
+        vbmeta_offset = be64toh(footer->vbmeta_offset);
+    }
+    // Ensures there is AVB_MAGIC at vbmeta_offset.
+    if (0 != data.compare(vbmeta_offset, AVB_MAGIC_LEN, AVB_MAGIC)) {
+        die("Failed to find AVB_MAGIC at offset: %" PRId64, vbmeta_offset);
+    }
+
+    fprintf(stderr, "Rewriting vbmeta struct at offset: %" PRId64 "\n", vbmeta_offset);
+
     // There's a 32-bit big endian |flags| field at offset 120 where
     // bit 0 corresponds to disable-verity and bit 1 corresponds to
     // disable-verification.
     //
     // See external/avb/libavb/avb_vbmeta_image.h for the layout of
     // the VBMeta struct.
+    uint64_t flags_offset = 123 + vbmeta_offset;
     if (g_disable_verity) {
-        data[123] |= 0x01;
+        data[flags_offset] |= 0x01;
     }
     if (g_disable_verification) {
-        data[123] |= 0x02;
+        data[flags_offset] |= 0x02;
     }
 
+    int fd = make_temporary_fd("vbmeta rewriting");
     if (!android::base::WriteStringToFd(data, fd)) {
         die("Failed writing to modified vbmeta");
     }
@@ -951,14 +979,25 @@
     lseek(fd, 0, SEEK_SET);
 }
 
+static bool has_vbmeta_partition() {
+    std::string partition_type;
+    return fb->GetVar("partition-type:vbmeta", &partition_type) == fastboot::SUCCESS ||
+           fb->GetVar("partition-type:vbmeta_a", &partition_type) == fastboot::SUCCESS ||
+           fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
+}
+
 static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
 {
     sparse_file** s;
 
     // Rewrite vbmeta if that's what we're flashing and modification has been requested.
-    if ((g_disable_verity || g_disable_verification) &&
-        (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b")) {
-        rewrite_vbmeta_buffer(buf);
+    if (g_disable_verity || g_disable_verification) {
+        if (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b") {
+            rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
+        } else if (!has_vbmeta_partition() &&
+                   (partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
+            rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */ );
+        }
     }
 
     switch (buf->type) {
@@ -1183,6 +1222,14 @@
     target_sparse_limit = -1;
 }
 
+static void CancelSnapshotIfNeeded() {
+    std::string merge_status = "none";
+    if (fb->GetVar(FB_VAR_SNAPSHOT_UPDATE_STATUS, &merge_status) == fastboot::SUCCESS &&
+        merge_status != "none") {
+        fb->SnapshotUpdateCommand("cancel");
+    }
+}
+
 class ImageSource {
   public:
     virtual bool ReadFile(const std::string& name, std::vector<char>* out) const = 0;
@@ -1235,6 +1282,8 @@
     DetermineSecondarySlot();
     CollectImages();
 
+    CancelSnapshotIfNeeded();
+
     // First flash boot partitions. We allow this to happen either in userspace
     // or in bootloader fastboot.
     FlashImages(boot_images_);
@@ -1584,6 +1633,76 @@
     return false;
 }
 
+static bool wipe_super(const android::fs_mgr::LpMetadata& metadata, const std::string& slot,
+                       std::string* message) {
+    auto super_device = GetMetadataSuperBlockDevice(metadata);
+    auto block_size = metadata.geometry.logical_block_size;
+    auto super_bdev_name = android::fs_mgr::GetBlockDevicePartitionName(*super_device);
+
+    if (super_bdev_name != "super") {
+        // retrofit devices do not allow flashing to the retrofit partitions,
+        // so enable it if we can.
+        fb->RawCommand("oem allow-flash-super");
+    }
+
+    // Note: do not use die() in here, since we want TemporaryDir's destructor
+    // to be called.
+    TemporaryDir temp_dir;
+
+    bool ok;
+    if (metadata.block_devices.size() > 1) {
+        ok = WriteSplitImageFiles(temp_dir.path, metadata, block_size, {}, true);
+    } else {
+        auto image_path = temp_dir.path + "/"s + super_bdev_name + ".img";
+        ok = WriteToImageFile(image_path, metadata, block_size, {}, true);
+    }
+    if (!ok) {
+        *message = "Could not generate a flashable super image file";
+        return false;
+    }
+
+    for (const auto& block_device : metadata.block_devices) {
+        auto partition = android::fs_mgr::GetBlockDevicePartitionName(block_device);
+        bool force_slot = !!(block_device.flags & LP_BLOCK_DEVICE_SLOT_SUFFIXED);
+
+        std::string image_name;
+        if (metadata.block_devices.size() > 1) {
+            image_name = "super_" + partition + ".img";
+        } else {
+            image_name = partition + ".img";
+        }
+
+        auto image_path = temp_dir.path + "/"s + image_name;
+        auto flash = [&](const std::string& partition_name) {
+            do_flash(partition_name.c_str(), image_path.c_str());
+        };
+        do_for_partitions(partition, slot, flash, force_slot);
+
+        unlink(image_path.c_str());
+    }
+    return true;
+}
+
+static void do_wipe_super(const std::string& image, const std::string& slot_override) {
+    if (access(image.c_str(), R_OK) != 0) {
+        die("Could not read image: %s", image.c_str());
+    }
+    auto metadata = android::fs_mgr::ReadFromImageFile(image);
+    if (!metadata) {
+        die("Could not parse image: %s", image.c_str());
+    }
+
+    auto slot = slot_override;
+    if (slot.empty()) {
+        slot = get_current_slot();
+    }
+
+    std::string message;
+    if (!wipe_super(*metadata.get(), slot, &message)) {
+        die(message);
+    }
+}
+
 int FastBootTool::Main(int argc, char* argv[]) {
     bool wants_wipe = false;
     bool wants_reboot = false;
@@ -1960,12 +2079,32 @@
             } else {
                 syntax_error("expected 'wipe' or 'disable'");
             }
+        } else if (command == "wipe-super") {
+            std::string image;
+            if (args.empty()) {
+                image = find_item_given_name("super_empty.img");
+            } else {
+                image = next_arg(&args);
+            }
+            do_wipe_super(image, slot_override);
+        } else if (command == "snapshot-update") {
+            std::string arg;
+            if (!args.empty()) {
+                arg = next_arg(&args);
+            }
+            if (!arg.empty() && (arg != "cancel" && arg != "merge")) {
+                syntax_error("expected: snapshot-update [cancel|merge]");
+            }
+            fb->SnapshotUpdateCommand(arg);
         } else {
             syntax_error("unknown command %s", command.c_str());
         }
     }
 
     if (wants_wipe) {
+        if (force_flash) {
+            CancelSnapshotIfNeeded();
+        }
         std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
         for (const auto& partition : partitions) {
             std::string partition_type;
@@ -1977,10 +2116,10 @@
             if (partition == "userdata" && set_fbe_marker) {
                 fprintf(stderr, "setting FBE marker on initial userdata...\n");
                 std::string initial_userdata_dir = create_fbemarker_tmpdir();
-                fb_perform_format(partition, 1, "", "", initial_userdata_dir);
+                fb_perform_format(partition, 1, partition_type, "", initial_userdata_dir);
                 delete_fbemarker_tmpdir(initial_userdata_dir);
             } else {
-                fb_perform_format(partition, 1, "", "", "");
+                fb_perform_format(partition, 1, partition_type, "", "");
             }
         }
     }
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index fea0a77..8d534ea 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -122,6 +122,15 @@
                       response, info);
 }
 
+RetCode FastBootDriver::SnapshotUpdateCommand(const std::string& command, std::string* response,
+                                              std::vector<std::string>* info) {
+    prolog_(StringPrintf("Snapshot %s", command.c_str()));
+    std::string raw = FB_CMD_SNAPSHOT_UPDATE ":" + command;
+    auto result = RawCommand(raw, response, info);
+    epilog_(result);
+    return result;
+}
+
 RetCode FastBootDriver::FlashPartition(const std::string& partition,
                                        const std::vector<char>& data) {
     RetCode ret;
@@ -291,7 +300,7 @@
 RetCode FastBootDriver::UploadInner(const std::string& outfile, std::string* response,
                                     std::vector<std::string>* info) {
     RetCode ret;
-    int dsize;
+    int dsize = 0;
     if ((ret = RawCommand(FB_CMD_UPLOAD, response, info, &dsize))) {
         error_ = "Upload request failed: " + error_;
         return ret;
diff --git a/fastboot/fastboot_driver.h b/fastboot/fastboot_driver.h
index af02637..7265632 100644
--- a/fastboot/fastboot_driver.h
+++ b/fastboot/fastboot_driver.h
@@ -104,6 +104,8 @@
                       std::vector<std::string>* info = nullptr);
     RetCode Upload(const std::string& outfile, std::string* response = nullptr,
                    std::vector<std::string>* info = nullptr);
+    RetCode SnapshotUpdateCommand(const std::string& command, std::string* response = nullptr,
+                                  std::vector<std::string>* info = nullptr);
 
     /* HIGHER LEVEL COMMANDS -- Composed of the commands above */
     RetCode FlashPartition(const std::string& partition, const std::vector<char>& data);
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index f597f50..8a3c213 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -106,7 +106,7 @@
     kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator);
 
     if (kr != 0) {
-        ERR("Couldn't create a device interface iterator: (%08x)\n", kr);
+        WARN("Couldn't create a device interface iterator: (%08x)\n", kr);
         return -1;
     }
 
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index b00edb3..bf840f8 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -195,25 +195,28 @@
 ssize_t WindowsUsbTransport::Read(void* data, size_t len) {
     unsigned long time_out = 0;
     unsigned long read = 0;
+    size_t count = 0;
     int ret;
 
     DBG("usb_read %zu\n", len);
     if (nullptr != handle_) {
-        while (1) {
-            int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
+        while (len > 0) {
+            size_t xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
 
             ret = AdbReadEndpointSync(handle_->adb_read_pipe, data, xfer, &read, time_out);
             errno = GetLastError();
-            DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
-            if (ret) {
-                return read;
-            } else {
+            DBG("usb_read got: %lu, expected: %zu, errno: %d\n", read, xfer, errno);
+            if (ret == 0) {
                 // assume ERROR_INVALID_HANDLE indicates we are disconnected
                 if (errno == ERROR_INVALID_HANDLE)
                     usb_kick(handle_.get());
                 break;
             }
-            // else we timed out - try again
+            count += read;
+            len -= read;
+            data = (char*)data + read;
+
+            if (xfer != read || len == 0) return count;
         }
     } else {
         DBG("usb_read NULL handle\n");
diff --git a/fastboot/util.cpp b/fastboot/util.cpp
index d02b37f..900d6ea 100644
--- a/fastboot/util.cpp
+++ b/fastboot/util.cpp
@@ -53,6 +53,10 @@
     exit(EXIT_FAILURE);
 }
 
+void die(const std::string& str) {
+    die("%s", str.c_str());
+}
+
 void set_verbose() {
     g_verbose = true;
 }
diff --git a/fastboot/util.h b/fastboot/util.h
index 2535414..c719df2 100644
--- a/fastboot/util.h
+++ b/fastboot/util.h
@@ -15,4 +15,7 @@
 // use the same attribute for compile-time format string checking.
 void die(const char* fmt, ...) __attribute__((__noreturn__))
 __attribute__((__format__(__printf__, 1, 2)));
+
 void verbose(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
+
+void die(const std::string& str) __attribute__((__noreturn__));
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 4ee9624..34c64d2 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -26,15 +26,16 @@
     ],
 }
 
-cc_library {
-    // Do not ever allow this library to be vendor_available as a shared library.
-    // It does not have a stable interface.
-    name: "libfs_mgr",
+cc_defaults {
+    name: "libfs_mgr_defaults",
     defaults: ["fs_mgr_defaults"],
-    recovery_available: true,
     export_include_dirs: ["include"],
     include_dirs: ["system/vold"],
+    cflags: [
+        "-D_FILE_OFFSET_BITS=64",
+    ],
     srcs: [
+        "file_wait.cpp",
         "fs_mgr.cpp",
         "fs_mgr_format.cpp",
         "fs_mgr_verity.cpp",
@@ -42,6 +43,7 @@
         "fs_mgr_overlayfs.cpp",
         "fs_mgr_roots.cpp",
         "fs_mgr_vendor_overlay.cpp",
+        ":libfiemap_srcs",
     ],
     shared_libs: [
         "libbase",
@@ -72,6 +74,8 @@
     whole_static_libs: [
         "liblogwrap",
         "libdm",
+        "libext2_uuid",
+        "libfscrypt",
         "libfstab",
     ],
     cppflags: [
@@ -85,6 +89,42 @@
             ],
         },
     },
+    header_libs: [
+        "libfiemap_headers",
+    ],
+    export_header_lib_headers: [
+        "libfiemap_headers",
+    ],
+}
+
+// Two variants of libfs_mgr are provided: libfs_mgr and libfs_mgr_binder.
+// Use libfs_mgr in recovery, first-stage-init, or when libfiemap or overlayfs
+// is not used.
+//
+// Use libfs_mgr_binder when not in recovery/first-stage init, or when overlayfs
+// or libfiemap is needed. In this case, libfiemap will proxy over binder to
+// gsid.
+cc_library {
+    // Do not ever allow this library to be vendor_available as a shared library.
+    // It does not have a stable interface.
+    name: "libfs_mgr",
+    recovery_available: true,
+    defaults: [
+        "libfs_mgr_defaults",
+    ],
+    srcs: [
+        ":libfiemap_passthrough_srcs",
+    ],
+}
+
+cc_library {
+    // Do not ever allow this library to be vendor_available as a shared library.
+    // It does not have a stable interface.
+    name: "libfs_mgr_binder",
+    defaults: [
+        "libfs_mgr_defaults",
+        "libfiemap_binder_defaults",
+    ],
 }
 
 cc_library_static {
@@ -121,9 +161,14 @@
     shared_libs: [
         "libbootloader_message",
         "libbase",
+        "libcutils",
         "libcrypto",
+        "libext4_utils",
         "libfec",
         "libfs_mgr",
+        "liblog",
+        "liblp",
+        "libselinux",
     ],
     header_libs: [
         "libcutils_headers",
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index f89e598..f579078 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -1,33 +1,27 @@
-Android Overlayfs integration with adb remount
+Android OverlayFS Integration with adb Remount
 ==============================================
 
 Introduction
 ------------
 
-Users working with userdebug or eng builds expect to be able to
-remount the system partition as read-write and then add or modify
-any number of files without reflashing the system image, which is
-understandably efficient for a development cycle.
-Limited memory systems that chose to use readonly filesystems like
-*squashfs*, or *Logical Resizable Android Partitions* which land
-system partition images right-sized, and with filesystem that have
-been deduped on the block level to compress the content; means that
-either a remount is not possible directly, or when done offers
-little or no utility because of remaining space limitations or
-support logistics.
+Users working with userdebug or eng builds expect to be able to remount the
+system partition as read-write and then add or modify any number of files
+without reflashing the system image, which is efficient for a development cycle.
 
-*Overlayfs* comes to the rescue for these debug scenarios, and logic
-will _automatically_ setup backing storage for a writable filesystem
-as an upper reference, and mount overtop the lower.  These actions
-will be performed in the **adb disable-verity** and **adb remount**
-requests.
+Limited memory systems use read-only types of file systems or logical resizable
+Android partitions (LRAPs). These file systems land system partition images
+right-sized, and have been deduped at the block level to compress the content.
+This means that a remount either isn’t possible, or isn't useful because of
+space limitations or support logistics.
 
-Operations
-----------
+OverlayFS resolves these debug scenarios with the _adb disable-verity_ and
+_adb remount_ commands, which set up backing storage for a writable file
+system as an upper reference, and mount the lower reference on top.
 
-### Cookbook
+Performing a remount
+--------------------
 
-The typical action to utilize the remount facility is:
+Use the following sequence to perform the remount.
 
     $ adb root
     $ adb disable-verity
@@ -36,11 +30,11 @@
     $ adb root
     $ adb remount
 
-Followed by one of the following:
+Then enter one of the following sequences:
 
-    $ adb stop
+    $ adb shell stop
     $ adb sync
-    $ adb start
+    $ adb shell start
     $ adb reboot
 
 *or*
@@ -48,72 +42,87 @@
     $ adb push <source> <destination>
     $ adb reboot
 
-Note that the sequence above:
+Note that you can replace these two lines:
 
     $ adb disable-verity
     $ adb reboot
 
-*or*
-
-    $ adb remount
-
-can be replaced in both places with:
+with this line:
 
     $ adb remount -R
 
-which will not reboot if everything is already prepared and ready
-to go.
+**Note:** _adb reboot -R_ won’t reboot if the device is already in the adb remount state.
 
-None of this changes if *overlayfs* needs to be engaged.
-The decisions whether to use traditional direct filesystem remount,
-or one wrapped by *overlayfs* is automatically determined based on
-a probe of the filesystem types and space remaining.
+None of this changes if OverlayFS needs to be engaged.
+The decisions whether to use traditional direct file-system remount,
+or one wrapped by OverlayFS is automatically determined based on
+a probe of the file-system types and space remaining.
 
 ### Backing Storage
 
-When *overlayfs* logic is feasible, it will use either the
+When *OverlayFS* logic is feasible, it uses either the
 **/cache/overlay/** directory for non-A/B devices, or the
 **/mnt/scratch/overlay** directory for A/B devices that have
-access to *Logical Resizable Android Partitions*.
+access to *LRAP*.
+It is also possible for an A/B device to use the system_<other> partition
+for backing storage. eg: if booting off system_a+vendor_a, use system_b.
 The backing store is used as soon as possible in the boot
-process and can occur at first stage init, or at the
-mount_all init rc commands.
+process and can occur at first stage init, or when the
+*mount_all* commands are run in init RC scripts.
 
-This early as possible attachment of *overlayfs* means that
-*sepolicy* or *init* itself can also be pushed and used after
-the exec phases that accompany each stage.
+By attaching OverlayFS early, SEpolicy or init can be pushed and used after the exec phases of each stage.
 
 Caveats
 -------
 
-- Space used in the backing storage is on a file by file basis
-  and will require more space than if updated in place.  As such
-  it is important to be mindful of any wasted space, for instance
-  **BOARD_<partition>IMAGE_PARTITION_RESERVED_SIZE** being defined
-  will have a negative impact on the overall right-sizing of images
-  and thus free dynamic partition space.
-- Kernel must have CONFIG_OVERLAY_FS=y and will need to be patched
-  with "*overlayfs: override_creds=off option bypass creator_cred*"
-  if kernel is 4.4 or higher.
-  The patch is available on the upstream mailing list and the latest as of
-  Feb 8 2019 is https://lore.kernel.org/patchwork/patch/1009299/.
-  This patch adds an override_creds _mount_ option to overlayfs that
+- Backing storage requires more space than immutable storage, as backing is
+  done file by file. Be mindful of wasted space. For example, defining
+  **BOARD_IMAGE_PARTITION_RESERVED_SIZE** has a negative impact on the
+  right-sizing of images and requires more free dynamic partition space.
+- The kernel requires **CONFIG_OVERLAY_FS=y**. If the kernel version is higher
+  than 4.4, it requires source to be in line with android-common kernels. 
+  The patch series is available on the upstream mailing list and the latest as
+  of Sep 5 2019 is https://www.spinics.net/lists/linux-mtd/msg08331.html
+  This patch adds an override_creds _mount_ option to OverlayFS that
   permits legacy behavior for systems that do not have overlapping
   sepolicy rules, principals of least privilege, which is how Android behaves.
-- *adb enable-verity* will free up overlayfs and as a bonus the
-  device will be reverted pristine to before any content was updated.
-  Update engine does not take advantage of this, will perform a full OTA.
-- Update engine may not run if *fs_mgr_overlayfs_is_setup*() reports
-  true as adb remount overrides are incompatible with an OTA resources.
+  For 4.19 and higher a rework of the xattr handling to deal with recursion
+  is required. https://patchwork.kernel.org/patch/11117145/ is a start of that
+  adjustment.
+- _adb enable-verity_ frees up OverlayFS and reverts the device to the state
+  prior to content updates. The update engine performs a full OTA.
+- _adb remount_ overrides are incompatible with OTA resources, so the update
+  engine may not run if fs_mgr_overlayfs_is_setup() returns true.
+- If a dynamic partition runs out of space, making a logical partition larger
+  may fail because of the scratch partition. If this happens, clear the scratch
+  storage by running either either _fastboot flashall_ or _adb enable-verity_.
+  Then reinstate the overrides and continue.
 - For implementation simplicity on retrofit dynamic partition devices,
   take the whole alternate super (eg: if "*a*" slot, then the whole of
   "*system_b*").
   Since landing a filesystem on the alternate super physical device
   without differentiating if it is setup to support logical or physical,
   the alternate slot metadata and previous content will be lost.
-- If dynamic partitions runs out of space, resizing a logical
-  partition larger may fail because of the scratch partition.
-  If this happens, either fastboot flashall or adb enable-verity can
-  be used to clear scratch storage to permit the flash.
-  Then reinstate the overrides and continue.
+- There are other subtle caveats requiring complex logic to solve.
+  Have evaluated them as too complex or not worth the trouble, please
+  File a bug if a use case needs to be covered.
+  - The backing storage is treated fragile, if anything else has
+    issue with the space taken, the backing storage will be cleared
+    out and we reserve the right to not inform, if the layering
+    does not prevent any messaging.
+  - Space remaining threshold is hard coded.  If 1% or more space
+    still remains, OverlayFS will not be used, yet that amount of
+    space remaining is problematic.
+  - Flashing a partition via bootloader fastboot, as opposed to user
+    space fastbootd, is not detected, thus a partition may have
+    override content remaining.  adb enable-verity to wipe.
+  - Space is limited, there is near unlimited space on userdata,
+    we have made an architectural decision to not utilize
+    /data/overlay/ at this time.  Acquiring space to use for
+    backing remains an ongoing battle.
+  - First stage init, or ramdisk, can not be overriden.
+  - Backing storage will be discarded or ignored on errors, leading
+    to confusion.  When debugging using **adb remount** it is
+    currently advised to confirm update is present after a reboot
+    to develop confidence.
 - File bugs or submit fixes for review.
diff --git a/fs_mgr/file_wait.cpp b/fs_mgr/file_wait.cpp
new file mode 100644
index 0000000..cbf6845
--- /dev/null
+++ b/fs_mgr/file_wait.cpp
@@ -0,0 +1,235 @@
+// 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 <fs_mgr/file_wait.h>
+
+#include <limits.h>
+#if defined(__linux__)
+#include <poll.h>
+#include <sys/inotify.h>
+#endif
+#if defined(WIN32)
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <functional>
+#include <thread>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace fs_mgr {
+
+using namespace std::literals;
+using android::base::unique_fd;
+
+bool PollForFile(const std::string& path, const std::chrono::milliseconds relative_timeout) {
+    auto start_time = std::chrono::steady_clock::now();
+
+    while (true) {
+        if (!access(path.c_str(), F_OK) || errno != ENOENT) return true;
+
+        std::this_thread::sleep_for(50ms);
+
+        auto now = std::chrono::steady_clock::now();
+        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+        if (time_elapsed > relative_timeout) return false;
+    }
+}
+
+bool PollForFileDeleted(const std::string& path, const std::chrono::milliseconds relative_timeout) {
+    auto start_time = std::chrono::steady_clock::now();
+
+    while (true) {
+        if (access(path.c_str(), F_OK) && errno == ENOENT) return true;
+
+        std::this_thread::sleep_for(50ms);
+
+        auto now = std::chrono::steady_clock::now();
+        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+        if (time_elapsed > relative_timeout) return false;
+    }
+}
+
+#if defined(__linux__)
+class OneShotInotify {
+  public:
+    OneShotInotify(const std::string& path, uint32_t mask,
+                   const std::chrono::milliseconds relative_timeout);
+
+    bool Wait();
+
+  private:
+    bool CheckCompleted();
+    int64_t RemainingMs() const;
+    bool ConsumeEvents();
+
+    enum class Result { Success, Timeout, Error };
+    Result WaitImpl();
+
+    unique_fd inotify_fd_;
+    std::string path_;
+    uint32_t mask_;
+    std::chrono::time_point<std::chrono::steady_clock> start_time_;
+    std::chrono::milliseconds relative_timeout_;
+    bool finished_;
+};
+
+OneShotInotify::OneShotInotify(const std::string& path, uint32_t mask,
+                               const std::chrono::milliseconds relative_timeout)
+    : path_(path),
+      mask_(mask),
+      start_time_(std::chrono::steady_clock::now()),
+      relative_timeout_(relative_timeout),
+      finished_(false) {
+    // If the condition is already met, don't bother creating an inotify.
+    if (CheckCompleted()) return;
+
+    unique_fd inotify_fd(inotify_init1(IN_CLOEXEC | IN_NONBLOCK));
+    if (inotify_fd < 0) {
+        PLOG(ERROR) << "inotify_init1 failed";
+        return;
+    }
+
+    std::string watch_path;
+    if (mask == IN_CREATE) {
+        watch_path = android::base::Dirname(path);
+    } else {
+        watch_path = path;
+    }
+    if (inotify_add_watch(inotify_fd, watch_path.c_str(), mask) < 0) {
+        PLOG(ERROR) << "inotify_add_watch failed";
+        return;
+    }
+
+    // It's possible the condition was met before the add_watch. Check for
+    // this and abort early if so.
+    if (CheckCompleted()) return;
+
+    inotify_fd_ = std::move(inotify_fd);
+}
+
+bool OneShotInotify::Wait() {
+    Result result = WaitImpl();
+    if (result == Result::Success) return true;
+    if (result == Result::Timeout) return false;
+
+    // Some kind of error with inotify occurred, so fallback to a poll.
+    std::chrono::milliseconds timeout(RemainingMs());
+    if (mask_ == IN_CREATE) {
+        return PollForFile(path_, timeout);
+    } else if (mask_ == IN_DELETE_SELF) {
+        return PollForFileDeleted(path_, timeout);
+    } else {
+        LOG(ERROR) << "Unknown inotify mask: " << mask_;
+        return false;
+    }
+}
+
+OneShotInotify::Result OneShotInotify::WaitImpl() {
+    // If the operation completed super early, we'll never have created an
+    // inotify instance.
+    if (finished_) return Result::Success;
+    if (inotify_fd_ < 0) return Result::Error;
+
+    while (true) {
+        auto remaining_ms = RemainingMs();
+        if (remaining_ms <= 0) return Result::Timeout;
+
+        struct pollfd event = {
+                .fd = inotify_fd_,
+                .events = POLLIN,
+                .revents = 0,
+        };
+        int rv = poll(&event, 1, static_cast<int>(remaining_ms));
+        if (rv <= 0) {
+            if (rv == 0 || errno == EINTR) {
+                continue;
+            }
+            PLOG(ERROR) << "poll for inotify failed";
+            return Result::Error;
+        }
+        if (event.revents & POLLERR) {
+            LOG(ERROR) << "error reading inotify for " << path_;
+            return Result::Error;
+        }
+
+        // Note that we don't bother checking what kind of event it is, since
+        // it's cheap enough to just see if the initial condition is satisified.
+        // If it's not, we consume all the events available and continue.
+        if (CheckCompleted()) return Result::Success;
+        if (!ConsumeEvents()) return Result::Error;
+    }
+}
+
+bool OneShotInotify::CheckCompleted() {
+    if (mask_ == IN_CREATE) {
+        finished_ = !access(path_.c_str(), F_OK) || errno != ENOENT;
+    } else if (mask_ == IN_DELETE_SELF) {
+        finished_ = access(path_.c_str(), F_OK) && errno == ENOENT;
+    } else {
+        LOG(ERROR) << "Unexpected mask: " << mask_;
+    }
+    return finished_;
+}
+
+bool OneShotInotify::ConsumeEvents() {
+    // According to the manpage, this is enough to read at least one event.
+    static constexpr size_t kBufferSize = sizeof(struct inotify_event) + NAME_MAX + 1;
+    char buffer[kBufferSize];
+
+    do {
+        ssize_t rv = TEMP_FAILURE_RETRY(read(inotify_fd_, buffer, sizeof(buffer)));
+        if (rv <= 0) {
+            if (rv == 0 || errno == EAGAIN) {
+                return true;
+            }
+            PLOG(ERROR) << "read inotify failed";
+            return false;
+        }
+    } while (true);
+}
+
+int64_t OneShotInotify::RemainingMs() const {
+    auto remaining = (std::chrono::steady_clock::now() - start_time_);
+    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(remaining);
+    return (relative_timeout_ - elapsed).count();
+}
+#endif
+
+bool WaitForFile(const std::string& path, const std::chrono::milliseconds relative_timeout) {
+#if defined(__linux__)
+    OneShotInotify inotify(path, IN_CREATE, relative_timeout);
+    return inotify.Wait();
+#else
+    return PollForFile(path, relative_timeout);
+#endif
+}
+
+// Wait at most |relative_timeout| milliseconds for |path| to stop existing.
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds relative_timeout) {
+#if defined(__linux__)
+    OneShotInotify inotify(path, IN_DELETE_SELF, relative_timeout);
+    return inotify.Wait();
+#else
+    return PollForFileDeleted(path, relative_timeout);
+#endif
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index f753f54..15c9dfb 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -34,6 +34,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <chrono>
 #include <functional>
 #include <map>
 #include <memory>
@@ -42,6 +43,7 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
@@ -56,7 +58,9 @@
 #include <ext4_utils/ext4_utils.h>
 #include <ext4_utils/wipe.h>
 #include <fs_avb/fs_avb.h>
+#include <fs_mgr/file_wait.h>
 #include <fs_mgr_overlayfs.h>
+#include <fscrypt/fscrypt.h>
 #include <libdm/dm.h>
 #include <liblp/metadata_format.h>
 #include <linux/fs.h>
@@ -83,11 +87,16 @@
 
 #define SYSFS_EXT4_VERITY "/sys/fs/ext4/features/verity"
 
+// FIXME: this should be in system/extras
+#define EXT4_FEATURE_COMPAT_STABLE_INODES 0x0800
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
 using android::base::Basename;
+using android::base::GetBoolProperty;
 using android::base::Realpath;
 using android::base::StartsWith;
+using android::base::Timer;
 using android::base::unique_fd;
 using android::dm::DeviceMapper;
 using android::dm::DmDeviceState;
@@ -116,28 +125,6 @@
     FS_STAT_ENABLE_VERITY_FAILED = 0x80000,
 };
 
-// TODO: switch to inotify()
-bool fs_mgr_wait_for_file(const std::string& filename,
-                          const std::chrono::milliseconds relative_timeout,
-                          FileWaitMode file_wait_mode) {
-    auto start_time = std::chrono::steady_clock::now();
-
-    while (true) {
-        int rv = access(filename.c_str(), F_OK);
-        if (file_wait_mode == FileWaitMode::Exists) {
-            if (!rv || errno != ENOENT) return true;
-        } else if (file_wait_mode == FileWaitMode::DoesNotExist) {
-            if (rv && errno == ENOENT) return true;
-        }
-
-        std::this_thread::sleep_for(50ms);
-
-        auto now = std::chrono::steady_clock::now();
-        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
-        if (time_elapsed > relative_timeout) return false;
-    }
-}
-
 static void log_fs_stat(const std::string& blk_device, int fs_stat) {
     if ((fs_stat & FS_STAT_IS_EXT4) == 0) return; // only log ext4
     std::string msg =
@@ -243,13 +230,11 @@
         } else {
             LINFO << "Running " << E2FSCK_BIN << " on " << realpath(blk_device);
             if (should_force_check(*fs_stat)) {
-                ret = android_fork_execvp_ext(
-                    ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status,
-                    true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
+                ret = logwrap_fork_execvp(ARRAY_SIZE(e2fsck_forced_argv), e2fsck_forced_argv,
+                                          &status, false, LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
             } else {
-                ret = android_fork_execvp_ext(
-                    ARRAY_SIZE(e2fsck_argv), const_cast<char**>(e2fsck_argv), &status, true,
-                    LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
+                ret = logwrap_fork_execvp(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, &status, false,
+                                          LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
             }
 
             if (ret < 0) {
@@ -267,14 +252,12 @@
 
         if (should_force_check(*fs_stat)) {
             LINFO << "Running " << F2FS_FSCK_BIN << " -f " << realpath(blk_device);
-            ret = android_fork_execvp_ext(
-                ARRAY_SIZE(f2fs_fsck_forced_argv), const_cast<char**>(f2fs_fsck_forced_argv), &status,
-                true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
+            ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv,
+                                      &status, false, LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
         } else {
             LINFO << "Running " << F2FS_FSCK_BIN << " -a " << realpath(blk_device);
-            ret = android_fork_execvp_ext(
-                ARRAY_SIZE(f2fs_fsck_argv), const_cast<char**>(f2fs_fsck_argv), &status, true,
-                LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), nullptr, 0);
+            ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false,
+                                      LOG_KLOG | LOG_FILE, true, FSCK_LOG_FILE);
         }
         if (ret < 0) {
             /* No need to check for error in fork, we can't really handle it now */
@@ -352,8 +335,7 @@
 static bool run_tune2fs(const char* argv[], int argc) {
     int ret;
 
-    ret = android_fork_execvp_ext(argc, const_cast<char**>(argv), nullptr, true,
-                                  LOG_KLOG | LOG_FILE, true, nullptr, nullptr, 0);
+    ret = logwrap_fork_execvp(argc, argv, nullptr, false, LOG_KLOG, true, nullptr);
     return ret == 0;
 }
 
@@ -438,25 +420,43 @@
 // Enable file-based encryption if needed.
 static void tune_encrypt(const std::string& blk_device, const FstabEntry& entry,
                          const struct ext4_super_block* sb, int* fs_stat) {
-    bool has_encrypt = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_ENCRYPT)) != 0;
-    bool want_encrypt = entry.fs_mgr_flags.file_encryption;
-
-    if (has_encrypt || !want_encrypt) {
+    if (!entry.fs_mgr_flags.file_encryption) {
+        return;  // Nothing needs done.
+    }
+    std::vector<std::string> features_needed;
+    if ((sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_ENCRYPT)) == 0) {
+        features_needed.emplace_back("encrypt");
+    }
+    android::fscrypt::EncryptionOptions options;
+    if (!android::fscrypt::ParseOptions(entry.encryption_options, &options)) {
+        LERROR << "Unable to parse encryption options on " << blk_device << ": "
+               << entry.encryption_options;
         return;
     }
-
+    if ((options.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) != 0) {
+        // We can only use this policy on ext4 if the "stable_inodes" feature
+        // is set on the filesystem, otherwise shrinking will break encrypted files.
+        if ((sb->s_feature_compat & cpu_to_le32(EXT4_FEATURE_COMPAT_STABLE_INODES)) == 0) {
+            features_needed.emplace_back("stable_inodes");
+        }
+    }
+    if (features_needed.size() == 0) {
+        return;
+    }
     if (!tune2fs_available()) {
         LERROR << "Unable to enable ext4 encryption on " << blk_device
                << " because " TUNE2FS_BIN " is missing";
         return;
     }
 
-    const char* argv[] = {TUNE2FS_BIN, "-Oencrypt", blk_device.c_str()};
+    auto flags = android::base::Join(features_needed, ',');
+    auto flag_arg = "-O"s + flags;
+    const char* argv[] = {TUNE2FS_BIN, flag_arg.c_str(), blk_device.c_str()};
 
-    LINFO << "Enabling ext4 encryption on " << blk_device;
+    LINFO << "Enabling ext4 flags " << flags << " on " << blk_device;
     if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
         LERROR << "Failed to run " TUNE2FS_BIN " to enable "
-               << "ext4 encryption on " << blk_device;
+               << "ext4 flags " << flags << " on " << blk_device;
         *fs_stat |= FS_STAT_ENABLE_ENCRYPTION_FAILED;
     }
 }
@@ -873,37 +873,22 @@
     }
 }
 
-static bool call_vdc(const std::vector<std::string>& args) {
+static bool call_vdc(const std::vector<std::string>& args, int* ret) {
     std::vector<char const*> argv;
     argv.emplace_back("/system/bin/vdc");
     for (auto& arg : args) {
         argv.emplace_back(arg.c_str());
     }
     LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
-    int ret =
-            android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), nullptr, false, true);
-    if (ret != 0) {
-        LOG(ERROR) << "vdc returned error code: " << ret;
-        return false;
-    }
-    LOG(DEBUG) << "vdc finished successfully";
-    return true;
-}
-
-static bool call_vdc_ret(const std::vector<std::string>& args, int* ret) {
-    std::vector<char const*> argv;
-    argv.emplace_back("/system/bin/vdc");
-    for (auto& arg : args) {
-        argv.emplace_back(arg.c_str());
-    }
-    LOG(INFO) << "Calling: " << android::base::Join(argv, ' ');
-    int err = android_fork_execvp(argv.size(), const_cast<char**>(argv.data()), ret, false, true);
+    int err = logwrap_fork_execvp(argv.size(), argv.data(), ret, false, LOG_ALOG, false, nullptr);
     if (err != 0) {
         LOG(ERROR) << "vdc call failed with error code: " << err;
         return false;
     }
     LOG(DEBUG) << "vdc finished successfully";
-    *ret = WEXITSTATUS(*ret);
+    if (ret != nullptr) {
+        *ret = WEXITSTATUS(*ret);
+    }
     return true;
 }
 
@@ -929,22 +914,27 @@
   public:
     CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
 
+    bool NeedsCheckpoint() {
+        if (needs_checkpoint_ != UNKNOWN) {
+            return needs_checkpoint_ == YES;
+        }
+        if (!call_vdc({"checkpoint", "needsCheckpoint"}, &needs_checkpoint_)) {
+            LERROR << "Failed to find if checkpointing is needed. Assuming no.";
+            needs_checkpoint_ = NO;
+        }
+        return needs_checkpoint_ == YES;
+    }
+
     bool Update(FstabEntry* entry, const std::string& block_device = std::string()) {
         if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
             return true;
         }
 
         if (entry->fs_mgr_flags.checkpoint_blk) {
-            call_vdc({"checkpoint", "restoreCheckpoint", entry->blk_device});
+            call_vdc({"checkpoint", "restoreCheckpoint", entry->blk_device}, nullptr);
         }
 
-        if (needs_checkpoint_ == UNKNOWN &&
-            !call_vdc_ret({"checkpoint", "needsCheckpoint"}, &needs_checkpoint_)) {
-            LERROR << "Failed to find if checkpointing is needed. Assuming no.";
-            needs_checkpoint_ = NO;
-        }
-
-        if (needs_checkpoint_ != YES) {
+        if (!NeedsCheckpoint()) {
             return true;
         }
 
@@ -1132,6 +1122,12 @@
             continue;
         }
 
+        // Terrible hack to make it possible to remount /data.
+        // TODO: refact fs_mgr_mount_all and get rid of this.
+        if (mount_mode == MOUNT_MODE_ONLY_USERDATA && current_entry.mount_point != "/data") {
+            continue;
+        }
+
         // Translate LABEL= file system labels into block devices.
         if (is_extfs(current_entry.fs_type)) {
             if (!TranslateExtLabels(&current_entry)) {
@@ -1151,8 +1147,7 @@
             continue;
         }
 
-        if (current_entry.fs_mgr_flags.wait &&
-            !fs_mgr_wait_for_file(current_entry.blk_device, 20s)) {
+        if (current_entry.fs_mgr_flags.wait && !WaitForFile(current_entry.blk_device, 20s)) {
             LERROR << "Skipping '" << current_entry.blk_device << "' during mount_all";
             continue;
         }
@@ -1215,7 +1210,8 @@
                 encryptable = status;
                 if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
                     if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.blk_device,
-                                   attempted_entry.mount_point})) {
+                                   attempted_entry.mount_point},
+                                  nullptr)) {
                         LERROR << "Encryption failed";
                         return FS_MGR_MNTALL_FAIL;
                     }
@@ -1287,7 +1283,8 @@
         } else if (mount_errno != EBUSY && mount_errno != EACCES &&
                    should_use_metadata_encryption(attempted_entry)) {
             if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.blk_device,
-                           attempted_entry.mount_point})) {
+                           attempted_entry.mount_point},
+                          nullptr)) {
                 ++error_count;
             }
             encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
@@ -1353,7 +1350,7 @@
                 continue;
             }
         } else if ((current_entry.fs_mgr_flags.verify)) {
-            if (!fs_mgr_teardown_verity(&current_entry, true /* wait */)) {
+            if (!fs_mgr_teardown_verity(&current_entry)) {
                 LERROR << "Failed to tear down verified partition on mount point: "
                        << current_entry.mount_point;
                 ret |= FsMgrUmountStatus::ERROR_VERITY;
@@ -1364,6 +1361,108 @@
     return ret;
 }
 
+static bool fs_mgr_unmount_all_data_mounts(const std::string& block_device) {
+    Timer t;
+    // TODO(b/135984674): should be configured via a read-only property.
+    std::chrono::milliseconds timeout = 5s;
+    while (true) {
+        bool umount_done = true;
+        Fstab proc_mounts;
+        if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
+            LERROR << "Can't read /proc/mounts";
+            return false;
+        }
+        // Now proceed with other bind mounts on top of /data.
+        for (const auto& entry : proc_mounts) {
+            if (entry.blk_device == block_device) {
+                if (umount2(entry.mount_point.c_str(), 0) != 0) {
+                    umount_done = false;
+                }
+            }
+        }
+        if (umount_done) {
+            LINFO << "Unmounting /data took " << t;
+            return true;
+        }
+        if (t.duration() > timeout) {
+            return false;
+        }
+        std::this_thread::sleep_for(50ms);
+    }
+}
+
+// TODO(b/143970043): return different error codes based on which step failed.
+int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
+    Fstab proc_mounts;
+    if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
+        LERROR << "Can't read /proc/mounts";
+        return -1;
+    }
+    std::string block_device;
+    if (auto entry = GetEntryForMountPoint(&proc_mounts, "/data"); entry != nullptr) {
+        block_device = entry->blk_device;
+    } else {
+        LERROR << "/data is not mounted";
+        return -1;
+    }
+    auto fstab_entry = GetMountedEntryForUserdata(fstab);
+    if (fstab_entry == nullptr) {
+        LERROR << "Can't find /data in fstab";
+        return -1;
+    }
+    if (!fstab_entry->fs_mgr_flags.checkpoint_blk && !fstab_entry->fs_mgr_flags.checkpoint_fs) {
+        LINFO << "Userdata doesn't support checkpointing. Nothing to do";
+        return 0;
+    }
+    CheckpointManager checkpoint_manager;
+    if (!checkpoint_manager.NeedsCheckpoint()) {
+        LINFO << "Checkpointing not needed. Don't remount";
+        return 0;
+    }
+    bool force_umount_for_f2fs =
+            GetBoolProperty("sys.init.userdata_remount.force_umount_f2fs", false);
+    if (fstab_entry->fs_mgr_flags.checkpoint_fs && !force_umount_for_f2fs) {
+        // Userdata is f2fs, simply remount it.
+        if (!checkpoint_manager.Update(fstab_entry)) {
+            LERROR << "Failed to remount userdata in checkpointing mode";
+            return -1;
+        }
+        if (mount(block_device.c_str(), fstab_entry->mount_point.c_str(), "none",
+                  MS_REMOUNT | fstab_entry->flags, fstab_entry->fs_options.c_str()) != 0) {
+            PERROR << "Failed to remount userdata in checkpointing mode";
+            return -1;
+        }
+    } else {
+        LINFO << "Unmounting /data before remounting into checkpointing mode";
+        if (!fs_mgr_unmount_all_data_mounts(block_device)) {
+            LERROR << "Failed to umount /data";
+            return -1;
+        }
+        DeviceMapper& dm = DeviceMapper::Instance();
+        while (dm.IsDmBlockDevice(block_device)) {
+            auto next_device = dm.GetParentBlockDeviceByPath(block_device);
+            auto name = dm.GetDmDeviceNameByPath(block_device);
+            if (!name) {
+                LERROR << "Failed to get dm-name for " << block_device;
+                return -1;
+            }
+            LINFO << "Deleting " << block_device << " named " << *name;
+            if (!dm.DeleteDevice(*name, 3s)) {
+                return -1;
+            }
+            if (!next_device) {
+                LERROR << "Failed to find parent device for " << block_device;
+            }
+            block_device = *next_device;
+        }
+        LINFO << "Remounting /data";
+        // TODO(b/143970043): remove this hack after fs_mgr_mount_all is refactored.
+        int result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA);
+        return result == FS_MGR_MNTALL_FAIL ? -1 : 0;
+    }
+    return 0;
+}
+
 // wrapper to __mount() and expects a fully prepared fstab_rec,
 // unlike fs_mgr_do_mount which does more things with avb / verity etc.
 int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point) {
@@ -1423,7 +1522,7 @@
         }
 
         // First check the filesystem if requested.
-        if (fstab_entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(n_blk_device, 20s)) {
+        if (fstab_entry.fs_mgr_flags.wait && !WaitForFile(n_blk_device, 20s)) {
             LERROR << "Skipping mounting '" << n_blk_device << "'";
             continue;
         }
@@ -1626,7 +1725,7 @@
             fprintf(zram_fp.get(), "%" PRId64 "\n", entry.zram_size);
         }
 
-        if (entry.fs_mgr_flags.wait && !fs_mgr_wait_for_file(entry.blk_device, 20s)) {
+        if (entry.fs_mgr_flags.wait && !WaitForFile(entry.blk_device, 20s)) {
             LERROR << "Skipping mkswap for '" << entry.blk_device << "'";
             ret = false;
             continue;
@@ -1637,10 +1736,8 @@
                 MKSWAP_BIN,
                 entry.blk_device.c_str(),
         };
-        int err = 0;
-        int status;
-        err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), const_cast<char**>(mkswap_argv),
-                                      &status, true, LOG_KLOG, false, nullptr, nullptr, 0);
+        int err = logwrap_fork_execvp(ARRAY_SIZE(mkswap_argv), mkswap_argv, nullptr, false,
+                                      LOG_KLOG, false, nullptr);
         if (err) {
             LERROR << "mkswap failed for " << entry.blk_device;
             ret = false;
@@ -1666,38 +1763,6 @@
     return ret;
 }
 
-bool fs_mgr_load_verity_state(int* mode) {
-    /* return the default mode, unless any of the verified partitions are in
-     * logging mode, in which case return that */
-    *mode = VERITY_MODE_DEFAULT;
-
-    Fstab fstab;
-    if (!ReadDefaultFstab(&fstab)) {
-        LERROR << "Failed to read default fstab";
-        return false;
-    }
-
-    for (const auto& entry : fstab) {
-        if (entry.fs_mgr_flags.avb) {
-            *mode = VERITY_MODE_RESTART;  // avb only supports restart mode.
-            break;
-        } else if (!entry.fs_mgr_flags.verify) {
-            continue;
-        }
-
-        int current;
-        if (load_verity_state(entry, &current) < 0) {
-            continue;
-        }
-        if (current != VERITY_MODE_DEFAULT) {
-            *mode = current;
-            break;
-        }
-    }
-
-    return true;
-}
-
 bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
     if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
         return false;
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index ee6ffdb..ea9c957 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -38,6 +38,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <fs_mgr/file_wait.h>
 #include <liblp/reader.h>
 
 #include "fs_mgr_priv.h"
@@ -51,45 +52,53 @@
 using DmTargetZero = android::dm::DmTargetZero;
 using DmTargetLinear = android::dm::DmTargetLinear;
 
-static bool GetPhysicalPartitionDevicePath(const LpMetadata& metadata,
+static bool GetPhysicalPartitionDevicePath(const IPartitionOpener& opener,
+                                           const LpMetadata& metadata,
                                            const LpMetadataBlockDevice& block_device,
-                                           const std::string& super_device,
-                                           std::string* result) {
-    // Note: device-mapper will not accept symlinks, so we must use realpath
-    // here.
-    std::string name = GetBlockDevicePartitionName(block_device);
-    std::string path = "/dev/block/by-name/" + name;
+                                           const std::string& super_device, std::string* result) {
     // If the super device is the source of this block device's metadata,
     // make sure we use the correct super device (and not just "super",
     // which might not exist.)
+    std::string name = GetBlockDevicePartitionName(block_device);
+    std::string dev_string = opener.GetDeviceString(name);
     if (GetMetadataSuperBlockDevice(metadata) == &block_device) {
-        path = super_device;
+        dev_string = opener.GetDeviceString(super_device);
     }
-    if (!android::base::Realpath(path, result)) {
-        PERROR << "realpath: " << path;
-        return false;
+
+    // Note: device-mapper will not accept symlinks, so we must use realpath
+    // here. If the device string is a major:minor sequence, we don't need to
+    // to call Realpath (it would not work anyway).
+    if (android::base::StartsWith(dev_string, "/")) {
+        if (!android::base::Realpath(dev_string, result)) {
+            PERROR << "realpath: " << dev_string;
+            return false;
+        }
+    } else {
+        *result = dev_string;
     }
     return true;
 }
 
-static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition,
-                          const std::string& super_device, DmTable* table) {
+bool CreateDmTableInternal(const CreateLogicalPartitionParams& params, DmTable* table) {
+    const auto& super_device = params.block_device;
+
     uint64_t sector = 0;
-    for (size_t i = 0; i < partition.num_extents; i++) {
-        const auto& extent = metadata.extents[partition.first_extent_index + i];
+    for (size_t i = 0; i < params.partition->num_extents; i++) {
+        const auto& extent = params.metadata->extents[params.partition->first_extent_index + i];
         std::unique_ptr<DmTarget> target;
         switch (extent.target_type) {
             case LP_TARGET_TYPE_ZERO:
                 target = std::make_unique<DmTargetZero>(sector, extent.num_sectors);
                 break;
             case LP_TARGET_TYPE_LINEAR: {
-                const auto& block_device = metadata.block_devices[extent.target_source];
-                std::string path;
-                if (!GetPhysicalPartitionDevicePath(metadata, block_device, super_device, &path)) {
+                const auto& block_device = params.metadata->block_devices[extent.target_source];
+                std::string dev_string;
+                if (!GetPhysicalPartitionDevicePath(*params.partition_opener, *params.metadata,
+                                                    block_device, super_device, &dev_string)) {
                     LOG(ERROR) << "Unable to complete device-mapper table, unknown block device";
                     return false;
                 }
-                target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, path,
+                target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, dev_string,
                                                           extent.target_data);
                 break;
             }
@@ -102,40 +111,19 @@
         }
         sector += extent.num_sectors;
     }
-    if (partition.attributes & LP_PARTITION_ATTR_READONLY) {
+    if (params.partition->attributes & LP_PARTITION_ATTR_READONLY) {
         table->set_readonly(true);
     }
+    if (params.force_writable) {
+        table->set_readonly(false);
+    }
     return true;
 }
 
-static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition,
-                                   bool force_writable, const std::chrono::milliseconds& timeout_ms,
-                                   const std::string& super_device, std::string* path) {
-    DeviceMapper& dm = DeviceMapper::Instance();
-
-    DmTable table;
-    if (!CreateDmTable(metadata, partition, super_device, &table)) {
-        return false;
-    }
-    if (force_writable) {
-        table.set_readonly(false);
-    }
-    std::string name = GetPartitionName(partition);
-    if (!dm.CreateDevice(name, table)) {
-        return false;
-    }
-    if (!dm.GetDmDevicePathByName(name, path)) {
-        return false;
-    }
-    if (timeout_ms > std::chrono::milliseconds::zero()) {
-        if (!fs_mgr_wait_for_file(*path, timeout_ms, FileWaitMode::Exists)) {
-            DestroyLogicalPartition(name, {});
-            LERROR << "Timed out waiting for device path: " << *path;
-            return false;
-        }
-    }
-    LINFO << "Created logical partition " << name << " on device " << *path;
-    return true;
+bool CreateDmTable(CreateLogicalPartitionParams params, DmTable* table) {
+    CreateLogicalPartitionParams::OwnedData owned_data;
+    if (!params.InitDefaults(&owned_data)) return false;
+    return CreateDmTableInternal(params, table);
 }
 
 bool CreateLogicalPartitions(const std::string& block_device) {
@@ -154,13 +142,24 @@
 }
 
 bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& super_device) {
+    CreateLogicalPartitionParams params = {
+            .block_device = super_device,
+            .metadata = &metadata,
+    };
     for (const auto& partition : metadata.partitions) {
         if (!partition.num_extents) {
             LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
             continue;
         }
-        std::string path;
-        if (!CreateLogicalPartition(metadata, partition, false, {}, super_device, &path)) {
+        if (partition.attributes & LP_PARTITION_ATTR_DISABLED) {
+            LINFO << "Skipping disabled partition: " << GetPartitionName(partition);
+            continue;
+        }
+
+        params.partition = &partition;
+
+        std::string ignore_path;
+        if (!CreateLogicalPartition(params, &ignore_path)) {
             LERROR << "Could not create logical partition: " << GetPartitionName(partition);
             return false;
         }
@@ -168,49 +167,98 @@
     return true;
 }
 
-bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
-                            const std::string& partition_name, bool force_writable,
-                            const std::chrono::milliseconds& timeout_ms, std::string* path) {
-    for (const auto& partition : metadata.partitions) {
-        if (GetPartitionName(partition) == partition_name) {
-            return CreateLogicalPartition(metadata, partition, force_writable, timeout_ms,
-                                          block_device, path);
-        }
-    }
-    LERROR << "Could not find any partition with name: " << partition_name;
-    return false;
-}
-
-bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
-                            const std::string& partition_name, bool force_writable,
-                            const std::chrono::milliseconds& timeout_ms, std::string* path) {
-    auto metadata = ReadMetadata(block_device.c_str(), metadata_slot);
-    if (!metadata) {
-        LOG(ERROR) << "Could not read partition table.";
-        return true;
-    }
-    return CreateLogicalPartition(block_device, *metadata.get(), partition_name, force_writable,
-                                  timeout_ms, path);
-}
-
-bool UnmapDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms) {
-    DeviceMapper& dm = DeviceMapper::Instance();
-    std::string path;
-    if (timeout_ms > std::chrono::milliseconds::zero()) {
-        dm.GetDmDevicePathByName(name, &path);
-    }
-    if (!dm.DeleteDevice(name)) {
+bool CreateLogicalPartitionParams::InitDefaults(CreateLogicalPartitionParams::OwnedData* owned) {
+    if (block_device.empty()) {
+        LOG(ERROR) << "block_device is required for CreateLogicalPartition";
         return false;
     }
-    if (!path.empty() && !fs_mgr_wait_for_file(path, timeout_ms, FileWaitMode::DoesNotExist)) {
-        LERROR << "Timed out waiting for device path to unlink: " << path;
+
+    if (!partition_opener) {
+        owned->partition_opener = std::make_unique<PartitionOpener>();
+        partition_opener = owned->partition_opener.get();
+    }
+
+    // Read metadata if needed.
+    if (!metadata) {
+        if (!metadata_slot) {
+            LOG(ERROR) << "Either metadata or a metadata slot must be specified.";
+            return false;
+        }
+        auto slot = *metadata_slot;
+        if (owned->metadata = ReadMetadata(*partition_opener, block_device, slot);
+            !owned->metadata) {
+            LOG(ERROR) << "Could not read partition table for: " << block_device;
+            return false;
+        }
+        metadata = owned->metadata.get();
+    }
+
+    // Find the partition by name if needed.
+    if (!partition) {
+        for (const auto& metadata_partition : metadata->partitions) {
+            if (android::fs_mgr::GetPartitionName(metadata_partition) == partition_name) {
+                partition = &metadata_partition;
+                break;
+            }
+        }
+    }
+    if (!partition) {
+        LERROR << "Could not find any partition with name: " << partition_name;
+        return false;
+    }
+    if (partition_name.empty()) {
+        partition_name = android::fs_mgr::GetPartitionName(*partition);
+    } else if (partition_name != android::fs_mgr::GetPartitionName(*partition)) {
+        LERROR << "Inconsistent partition_name " << partition_name << " with partition "
+               << android::fs_mgr::GetPartitionName(*partition);
+        return false;
+    }
+
+    if (device_name.empty()) {
+        device_name = partition_name;
+    }
+
+    return true;
+}
+
+bool CreateLogicalPartition(CreateLogicalPartitionParams params, std::string* path) {
+    CreateLogicalPartitionParams::OwnedData owned_data;
+    if (!params.InitDefaults(&owned_data)) return false;
+
+    DmTable table;
+    if (!CreateDmTableInternal(params, &table)) {
+        return false;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.CreateDevice(params.device_name, table, path, params.timeout_ms)) {
+        return false;
+    }
+    LINFO << "Created logical partition " << params.device_name << " on device " << *path;
+    return true;
+}
+
+std::string CreateLogicalPartitionParams::GetDeviceName() const {
+    if (!device_name.empty()) return device_name;
+    return GetPartitionName();
+}
+
+std::string CreateLogicalPartitionParams::GetPartitionName() const {
+    if (!partition_name.empty()) return partition_name;
+    if (partition) return android::fs_mgr::GetPartitionName(*partition);
+    return "<unknown partition>";
+}
+
+bool UnmapDevice(const std::string& name) {
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.DeleteDevice(name)) {
         return false;
     }
     return true;
 }
 
-bool DestroyLogicalPartition(const std::string& name, const std::chrono::milliseconds& timeout_ms) {
-    if (!UnmapDevice(name, timeout_ms)) {
+bool DestroyLogicalPartition(const std::string& name) {
+    if (!UnmapDevice(name)) {
         return false;
     }
     LINFO << "Unmapped logical partition " << name;
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 1c6652a..acf4d7b 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -76,8 +76,8 @@
             "/system/bin/mke2fs", "-t",   "ext4", "-b", "4096", fs_blkdev.c_str(),
             size_str.c_str(),     nullptr};
 
-    rc = android_fork_execvp_ext(arraysize(mke2fs_args), const_cast<char**>(mke2fs_args), NULL,
-                                 true, LOG_KLOG, true, nullptr, nullptr, 0);
+    rc = logwrap_fork_execvp(arraysize(mke2fs_args), mke2fs_args, nullptr, false, LOG_KLOG, true,
+                             nullptr);
     if (rc) {
         LERROR << "mke2fs returned " << rc;
         return rc;
@@ -86,8 +86,8 @@
     const char* const e2fsdroid_args[] = {
             "/system/bin/e2fsdroid", "-e", "-a", fs_mnt_point.c_str(), fs_blkdev.c_str(), nullptr};
 
-    rc = android_fork_execvp_ext(arraysize(e2fsdroid_args), const_cast<char**>(e2fsdroid_args),
-                                 NULL, true, LOG_KLOG, true, nullptr, nullptr, 0);
+    rc = logwrap_fork_execvp(arraysize(e2fsdroid_args), e2fsdroid_args, nullptr, false, LOG_KLOG,
+                             true, nullptr);
     if (rc) {
         LERROR << "e2fsdroid returned " << rc;
     }
@@ -119,8 +119,7 @@
     };
     // clang-format on
 
-    return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), NULL, true,
-                                   LOG_KLOG, true, nullptr, nullptr, 0);
+    return logwrap_fork_execvp(arraysize(args), args, nullptr, false, LOG_KLOG, true, nullptr);
 }
 
 int fs_mgr_do_format(const FstabEntry& entry, bool crypt_footer) {
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 7df7cfd..9697a4c 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -36,9 +36,11 @@
 
 #include "fs_mgr_priv.h"
 
+using android::base::EndsWith;
 using android::base::ParseByteCount;
 using android::base::ParseInt;
 using android::base::ReadFileToString;
+using android::base::Readlink;
 using android::base::Split;
 using android::base::StartsWith;
 
@@ -46,7 +48,7 @@
 namespace fs_mgr {
 namespace {
 
-const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
+constexpr char kDefaultAndroidDtDir[] = "/proc/device-tree/firmware/android";
 
 struct FlagList {
     const char *name;
@@ -98,58 +100,9 @@
     return false;
 }
 
-const std::array<const char*, 3> kFileContentsEncryptionMode = {
-        "aes-256-xts",
-        "adiantum",
-        "ice",
-};
-
-const std::array<const char*, 3> kFileNamesEncryptionMode = {
-        "aes-256-cts",
-        "aes-256-heh",
-        "adiantum",
-};
-
 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;
-
-    auto parts = Split(arg, ":");
-    if (parts.empty() || parts.size() > 2) {
-        LWARNING << "Warning: fileencryption= flag malformed: " << arg;
-        return;
-    }
-
-    // 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";
-    }
+    entry->encryption_options = arg;
 }
 
 bool SetMountFlag(const std::string& flag, FstabEntry* entry) {
@@ -171,6 +124,18 @@
                 fs_options.append(",");  // appends a comma if not the first
             }
             fs_options.append(flag);
+
+            if (entry->fs_type == "f2fs" && StartsWith(flag, "reserve_root=")) {
+                std::string arg;
+                if (auto equal_sign = flag.find('='); equal_sign != std::string::npos) {
+                    arg = flag.substr(equal_sign + 1);
+                }
+                if (!ParseInt(arg, &entry->reserved_size)) {
+                    LWARNING << "Warning: reserve_root= flag malformed: " << arg;
+                } else {
+                    entry->reserved_size <<= 12;
+                }
+            }
         }
     }
     entry->fs_options = std::move(fs_options);
@@ -262,10 +227,6 @@
                     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;
@@ -277,8 +238,7 @@
             // 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";
+            entry->encryption_options = "aes-256-xts:aes-256-cts";
         } else if (StartsWith(flag, "max_comp_streams=")) {
             if (!ParseInt(arg, &entry->max_comp_streams)) {
                 LWARNING << "Warning: max_comp_streams= flag malformed: " << arg;
@@ -590,7 +550,7 @@
     return boot_devices;
 }
 
-FstabEntry BuildGsiUserdataFstabEntry() {
+FstabEntry BuildDsuUserdataFstabEntry() {
     constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV;
 
     FstabEntry userdata = {
@@ -619,7 +579,11 @@
     return false;
 }
 
-void TransformFstabForGsi(Fstab* fstab) {
+}  // namespace
+
+void TransformFstabForDsu(Fstab* fstab, const std::vector<std::string>& dsu_partitions) {
+    static constexpr char kDsuKeysDir[] = "/avb";
+    // Convert userdata
     // Inherit fstab properties for userdata.
     FstabEntry userdata;
     if (FstabEntry* entry = GetEntryForMountPoint(fstab, "/data")) {
@@ -631,19 +595,65 @@
             userdata.key_dir += "/gsi";
         }
     } else {
-        userdata = BuildGsiUserdataFstabEntry();
-    }
-
-    if (EraseFstabEntry(fstab, "/system")) {
-        fstab->emplace_back(BuildGsiSystemFstabEntry());
+        userdata = BuildDsuUserdataFstabEntry();
     }
 
     if (EraseFstabEntry(fstab, "/data")) {
         fstab->emplace_back(userdata);
     }
-}
 
-}  // namespace
+    // Convert others
+    for (auto&& partition : dsu_partitions) {
+        if (!EndsWith(partition, gsi::kDsuPostfix)) {
+            continue;
+        }
+        // userdata has been handled
+        if (StartsWith(partition, "user")) {
+            continue;
+        }
+        // dsu_partition_name = corresponding_partition_name + kDsuPostfix
+        // e.g.
+        //    system_gsi for system
+        //    product_gsi for product
+        //    vendor_gsi for vendor
+        std::string lp_name = partition.substr(0, partition.length() - strlen(gsi::kDsuPostfix));
+        std::string mount_point = "/" + lp_name;
+        std::vector<FstabEntry*> entries = GetEntriesForMountPoint(fstab, mount_point);
+        if (entries.empty()) {
+            FstabEntry entry = {
+                    .blk_device = partition,
+                    // .logical_partition_name is required to look up AVB Hashtree descriptors.
+                    .logical_partition_name = "system",
+                    .mount_point = mount_point,
+                    .fs_type = "ext4",
+                    .flags = MS_RDONLY,
+                    .fs_options = "barrier=1",
+                    .avb_keys = kDsuKeysDir,
+            };
+            entry.fs_mgr_flags.wait = true;
+            entry.fs_mgr_flags.logical = true;
+            entry.fs_mgr_flags.first_stage_mount = true;
+        } else {
+            // If the corresponding partition exists, transform all its Fstab
+            // by pointing .blk_device to the DSU partition.
+            for (auto&& entry : entries) {
+                entry->blk_device = partition;
+                // AVB keys for DSU should always be under kDsuKeysDir.
+                entry->avb_keys += kDsuKeysDir;
+            }
+            // Make sure the ext4 is included to support GSI.
+            auto partition_ext4 =
+                    std::find_if(fstab->begin(), fstab->end(), [&](const auto& entry) {
+                        return entry.mount_point == mount_point && entry.fs_type == "ext4";
+                    });
+            if (partition_ext4 == fstab->end()) {
+                auto new_entry = *GetEntryForMountPoint(fstab, mount_point);
+                new_entry.fs_type = "ext4";
+                fstab->emplace_back(new_entry);
+            }
+        }
+    }
+}
 
 bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
     auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
@@ -659,7 +669,9 @@
         return false;
     }
     if (!is_proc_mounts && !access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
-        TransformFstabForGsi(fstab);
+        std::string lp_names;
+        ReadFileToString(gsi::kGsiLpNamesFile, &lp_names);
+        TransformFstabForDsu(fstab, Split(lp_names, ","));
     }
 
     SkipMountingPartitions(fstab);
@@ -696,13 +708,14 @@
     return true;
 }
 
-// For GSI to skip mounting /product and /product_services, until there are
-// well-defined interfaces between them and /system. Otherwise, the GSI flashed
-// on /system might not be able to work with /product and /product_services.
-// When they're skipped here, /system/product and /system/product_services in
-// GSI will be used.
+// For GSI to skip mounting /product and /system_ext, until there are well-defined interfaces
+// between them and /system. Otherwise, the GSI flashed on /system might not be able to work with
+// device-specific /product and /system_ext. skip_mount.cfg belongs to system_ext partition because
+// only common files for all targets can be put into system partition. It is under
+// /system/system_ext because GSI is a single system.img that includes the contents of system_ext
+// partition and product partition under /system/system_ext and /system/product, respectively.
 bool SkipMountingPartitions(Fstab* fstab) {
-    constexpr const char kSkipMountConfig[] = "/system/etc/init/config/skip_mount.cfg";
+    constexpr const char kSkipMountConfig[] = "/system/system_ext/etc/init/config/skip_mount.cfg";
 
     std::string skip_config;
     auto save_errno = errno;
@@ -719,6 +732,7 @@
                                  [&skip_mount_point](const auto& entry) {
                                      return entry.mount_point == skip_mount_point;
                                  });
+        if (it == fstab->end()) continue;
         fstab->erase(it, fstab->end());
         LOG(INFO) << "Skip mounting partition: " << skip_mount_point;
     }
@@ -769,6 +783,104 @@
     return nullptr;
 }
 
+std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path) {
+    std::vector<FstabEntry*> entries;
+    if (fstab == nullptr) {
+        return entries;
+    }
+
+    for (auto& entry : *fstab) {
+        if (entry.mount_point == path) {
+            entries.emplace_back(&entry);
+        }
+    }
+
+    return entries;
+}
+
+static std::string ResolveBlockDevice(const std::string& block_device) {
+    if (!StartsWith(block_device, "/dev/block/")) {
+        LWARNING << block_device << " is not a block device";
+        return block_device;
+    }
+    std::string name = block_device.substr(5);
+    if (!StartsWith(name, "block/dm-")) {
+        // Not a dm-device, but might be a symlink. Optimistically try to readlink.
+        std::string result;
+        if (Readlink(block_device, &result)) {
+            return result;
+        } else if (errno == EINVAL) {
+            // After all, it wasn't a symlink.
+            return block_device;
+        } else {
+            LERROR << "Failed to readlink " << block_device;
+            return "";
+        }
+    }
+    // It's a dm-device, let's find what's inside!
+    std::string sys_dir = "/sys/" + name;
+    while (true) {
+        std::string slaves_dir = sys_dir + "/slaves";
+        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
+        if (!dir) {
+            LERROR << "Failed to open " << slaves_dir;
+            return "";
+        }
+        std::string sub_device_name = "";
+        for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
+            if (entry->d_type != DT_LNK) continue;
+            if (!sub_device_name.empty()) {
+                LERROR << "Too many slaves in " << slaves_dir;
+                return "";
+            }
+            sub_device_name = entry->d_name;
+        }
+        if (sub_device_name.empty()) {
+            LERROR << "No slaves in " << slaves_dir;
+            return "";
+        }
+        if (!StartsWith(sub_device_name, "dm-")) {
+            // Not a dm-device! We can stop now.
+            return "/dev/block/" + sub_device_name;
+        }
+        // Still a dm-device, keep digging.
+        sys_dir = "/sys/block/" + sub_device_name;
+    }
+}
+
+FstabEntry* GetMountedEntryForUserdata(Fstab* fstab) {
+    Fstab mounts;
+    if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
+        LERROR << "Failed to read /proc/mounts";
+        return nullptr;
+    }
+    auto mounted_entry = GetEntryForMountPoint(&mounts, "/data");
+    if (mounted_entry == nullptr) {
+        LWARNING << "/data is not mounted";
+        return nullptr;
+    }
+    std::string resolved_block_device = ResolveBlockDevice(mounted_entry->blk_device);
+    if (resolved_block_device.empty()) {
+        return nullptr;
+    }
+    LINFO << "/data is mounted on " << resolved_block_device;
+    for (auto& entry : *fstab) {
+        if (entry.mount_point != "/data") {
+            continue;
+        }
+        std::string block_device;
+        if (!Readlink(entry.blk_device, &block_device)) {
+            LWARNING << "Failed to readlink " << entry.blk_device;
+            block_device = entry.blk_device;
+        }
+        if (block_device == resolved_block_device) {
+            return &entry;
+        }
+    }
+    LERROR << "Didn't find entry that was used to mount /data";
+    return nullptr;
+}
+
 std::set<std::string> GetBootDevices() {
     // First check the kernel commandline, then try the device tree otherwise
     std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
@@ -788,28 +900,14 @@
     return ExtraBootDevices(fstab);
 }
 
-FstabEntry BuildGsiSystemFstabEntry() {
-    // .logical_partition_name is required to look up AVB Hashtree descriptors.
-    FstabEntry system = {
-            .blk_device = "system_gsi",
-            .mount_point = "/system",
-            .fs_type = "ext4",
-            .flags = MS_RDONLY,
-            .fs_options = "barrier=1",
-            // could add more keys separated by ':'.
-            .avb_keys = "/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey",
-            .logical_partition_name = "system"};
-    system.fs_mgr_flags.wait = true;
-    system.fs_mgr_flags.logical = true;
-    system.fs_mgr_flags.first_stage_mount = true;
-    return system;
-}
-
 std::string GetVerityDeviceName(const FstabEntry& entry) {
     std::string base_device;
     if (entry.mount_point == "/") {
-        // In AVB, the dm device name is vroot instead of system.
-        base_device = entry.fs_mgr_flags.avb ? "vroot" : "system";
+        // When using system-as-root, the device name is fixed as "vroot".
+        if (entry.fs_mgr_flags.avb) {
+            return "vroot";
+        }
+        base_device = "system";
     } else {
         base_device = android::base::Basename(entry.mount_point);
     }
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index f21d529..c043754 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -43,6 +43,7 @@
 #include <android-base/unique_fd.h>
 #include <ext4_utils/ext4_utils.h>
 #include <fs_mgr.h>
+#include <fs_mgr/file_wait.h>
 #include <fs_mgr_dm_linear.h>
 #include <fs_mgr_overlayfs.h>
 #include <fstab/fstab.h>
@@ -132,7 +133,7 @@
     return ret | !rmdir(test_directory.c_str());
 }
 
-// At less than 1% free space return value of false,
+// At less than 1% or 8MB of free space return value of false,
 // means we will try to wrap with overlayfs.
 bool fs_mgr_filesystem_has_space(const std::string& mount_point) {
     // If we have access issues to find out space remaining, return true
@@ -144,9 +145,36 @@
         return true;
     }
 
-    static constexpr int kPercentThreshold = 1;  // 1%
+    static constexpr int kPercentThreshold = 1;                       // 1%
+    static constexpr unsigned long kSizeThreshold = 8 * 1024 * 1024;  // 8MB
 
-    return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100));
+    return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100)) &&
+           (vst.f_bfree * vst.f_bsize) >= kSizeThreshold;
+}
+
+const auto kPhysicalDevice = "/dev/block/by-name/"s;
+
+bool fs_mgr_update_blk_device(FstabEntry* entry) {
+    if (entry->fs_mgr_flags.logical) {
+        fs_mgr_update_logical_partition(entry);
+    }
+    if (fs_mgr_access(entry->blk_device)) {
+        return true;
+    }
+    if (entry->blk_device != "/dev/root") {
+        return false;
+    }
+
+    // special case for system-as-root (taimen and others)
+    auto blk_device = kPhysicalDevice + "system";
+    if (!fs_mgr_access(blk_device)) {
+        blk_device += fs_mgr_get_slot_suffix();
+        if (!fs_mgr_access(blk_device)) {
+            return false;
+        }
+    }
+    entry->blk_device = blk_device;
+    return true;
 }
 
 bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
@@ -156,19 +184,19 @@
     if (!fs_mgr_filesystem_has_space(entry->mount_point)) {
         return true;
     }
-    if (entry->fs_mgr_flags.logical) {
-        fs_mgr_update_logical_partition(entry);
+
+    // blk_device needs to be setup so we can check superblock.
+    // If we fail here, because during init first stage and have doubts.
+    if (!fs_mgr_update_blk_device(entry)) {
+        return true;
     }
+
+    // check if ext4 de-dupe
     auto save_errno = errno;
-    errno = 0;
     auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device);
     if (!has_shared_blocks && (entry->mount_point == "/system")) {
         has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device);
     }
-    // special case for first stage init for system as root (taimen)
-    if (!has_shared_blocks && (errno == ENOENT) && (entry->blk_device == "/dev/root")) {
-        has_shared_blocks = true;
-    }
     errno = save_errno;
     return has_shared_blocks;
 }
@@ -387,8 +415,6 @@
     return SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
 }
 
-const auto kPhysicalDevice = "/dev/block/by-name/"s;
-
 std::string fs_mgr_overlayfs_super_device(uint32_t slot_number) {
     return kPhysicalDevice + fs_mgr_get_super_partition_name(slot_number);
 }
@@ -414,13 +440,9 @@
     rmdir(kScratchMountPoint.c_str());
 }
 
-// reduce 'DM_DEV_STATUS failed for scratch: No such device or address' noise
-std::string scratch_device_cache;
-
 bool fs_mgr_overlayfs_teardown_scratch(const std::string& overlay, bool* change) {
     // umount and delete kScratchMountPoint storage if we have logical partitions
     if (overlay != kScratchMountPoint) return true;
-    scratch_device_cache.erase();
     auto slot_number = fs_mgr_overlayfs_slot_number();
     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
     if (!fs_mgr_rw_access(super_device)) return true;
@@ -443,7 +465,7 @@
     auto metadata = builder->Export();
     if (metadata && UpdatePartitionTable(super_device, *metadata.get(), slot_number)) {
         if (change) *change = true;
-        if (!DestroyLogicalPartition(partition_name, 0s)) return false;
+        if (!DestroyLogicalPartition(partition_name)) return false;
     } else {
         LERROR << "delete partition " << overlay;
         return false;
@@ -687,7 +709,7 @@
     }
     report = report + ")=";
 
-    auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_RELATIME,
+    auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
                      options.c_str());
     if (ret) {
         retval = false;
@@ -750,12 +772,13 @@
     entry.fs_type = mnt_type;
     if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4";
     if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs";
-    entry.flags = MS_RELATIME;
+    entry.flags = MS_NOATIME;
     if (readonly) {
         entry.flags |= MS_RDONLY;
     } else {
         fs_mgr_set_blk_ro(device_path, false);
     }
+    entry.fs_mgr_flags.check = true;
     auto save_errno = errno;
     auto mounted = fs_mgr_do_mount_one(entry) == 0;
     if (!mounted) {
@@ -788,26 +811,48 @@
     return "auto";
 }
 
-std::string fs_mgr_overlayfs_scratch_device() {
-    if (!scratch_device_cache.empty()) return scratch_device_cache;
-
-    // Is this a multiple super device (retrofit)?
+// Note: we do not check access() here except for the super partition, since
+// in first-stage init we wouldn't have registed by-name symlinks for "other"
+// partitions that won't be mounted.
+static std::string GetPhysicalScratchDevice() {
     auto slot_number = fs_mgr_overlayfs_slot_number();
     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
     auto path = fs_mgr_overlayfs_super_device(slot_number == 0);
-    if (super_device == path) {
-        // Create from within single super device;
-        auto& dm = DeviceMapper::Instance();
-        const auto partition_name = android::base::Basename(kScratchMountPoint);
-        if (!dm.GetDmDevicePathByName(partition_name, &path)) {
-            // non-DAP A/B device?
-            if (fs_mgr_access(super_device)) return "";
-            auto other_slot = fs_mgr_get_other_slot_suffix();
-            if (other_slot.empty()) return "";
-            path = kPhysicalDevice + "system" + other_slot;
-        }
+    if (super_device != path) {
+        return path;
     }
-    return scratch_device_cache = path;
+    if (fs_mgr_access(super_device)) {
+        // Do not try to use system_other on a DAP device.
+        return "";
+    }
+
+    auto other_slot = fs_mgr_get_other_slot_suffix();
+    if (!other_slot.empty()) {
+        return kPhysicalDevice + "system" + other_slot;
+    }
+    return "";
+}
+
+// This returns the scratch device that was detected during early boot (first-
+// stage init). If the device was created later, for example during setup for
+// the adb remount command, it can return an empty string since it does not
+// query ImageManager.
+static std::string GetBootScratchDevice() {
+    auto& dm = DeviceMapper::Instance();
+
+    // If there is a scratch partition allocated in /data or on super, we
+    // automatically prioritize that over super_other or system_other.
+    // Some devices, for example, have a write-protected eMMC and the
+    // super partition cannot be used even if it exists.
+    std::string device;
+    auto partition_name = android::base::Basename(kScratchMountPoint);
+    if (dm.GetState(partition_name) != DmDeviceState::INVALID &&
+        dm.GetDmDevicePathByName(partition_name, &device)) {
+        return device;
+    }
+
+    // There is no dynamic scratch, so try and find a physical one.
+    return GetPhysicalScratchDevice();
 }
 
 bool fs_mgr_overlayfs_make_scratch(const std::string& scratch_device, const std::string& mnt_type) {
@@ -833,25 +878,40 @@
     return true;
 }
 
-bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_device,
-                                     bool* partition_exists, bool* change) {
-    *scratch_device = fs_mgr_overlayfs_scratch_device();
-    *partition_exists = fs_mgr_rw_access(*scratch_device);
-    auto partition_create = !*partition_exists;
-    // Do we need to create a logical "scratch" partition?
-    if (!partition_create && android::base::StartsWith(*scratch_device, kPhysicalDevice)) {
-        return true;
+static void TruncatePartitionsWithSuffix(MetadataBuilder* builder, const std::string& suffix) {
+    auto& dm = DeviceMapper::Instance();
+
+    // Remove <other> partitions
+    for (const auto& group : builder->ListGroups()) {
+        for (const auto& part : builder->ListPartitionsInGroup(group)) {
+            const auto& name = part->name();
+            if (!android::base::EndsWith(name, suffix)) {
+                continue;
+            }
+            if (dm.GetState(name) != DmDeviceState::INVALID && !DestroyLogicalPartition(name)) {
+                continue;
+            }
+            builder->ResizePartition(builder->FindPartition(name), 0);
+        }
     }
+}
+
+// Create or update a scratch partition within super.
+static bool CreateDynamicScratch(std::string* scratch_device, bool* partition_exists,
+                                 bool* change) {
+    const auto partition_name = android::base::Basename(kScratchMountPoint);
+
+    auto& dm = DeviceMapper::Instance();
+    *partition_exists = dm.GetState(partition_name) != DmDeviceState::INVALID;
+
+    auto partition_create = !*partition_exists;
     auto slot_number = fs_mgr_overlayfs_slot_number();
     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
-    if (!fs_mgr_rw_access(super_device)) return false;
-    if (!fs_mgr_overlayfs_has_logical(fstab)) return false;
     auto builder = MetadataBuilder::New(super_device, slot_number);
     if (!builder) {
         LERROR << "open " << super_device << " metadata";
         return false;
     }
-    const auto partition_name = android::base::Basename(kScratchMountPoint);
     auto partition = builder->FindPartition(partition_name);
     *partition_exists = partition != nullptr;
     auto changed = false;
@@ -879,17 +939,26 @@
             // the adb remount overrides :-( .
             auto margin_size = uint64_t(3 * 256 * 1024);
             BlockDeviceInfo info;
-            if (builder->GetBlockDeviceInfo(partition_name, &info)) {
+            if (builder->GetBlockDeviceInfo(fs_mgr_get_super_partition_name(slot_number), &info)) {
                 margin_size = 3 * info.logical_block_size;
             }
             partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
                                       partition_size / 2);
             if (partition_size > partition->size()) {
                 if (!builder->ResizePartition(partition, partition_size)) {
-                    LERROR << "resize " << partition_name;
-                    return false;
+                    // Try to free up space by deallocating partitions in the other slot.
+                    TruncatePartitionsWithSuffix(builder.get(), fs_mgr_get_other_slot_suffix());
+
+                    partition_size =
+                            builder->AllocatableSpace() - builder->UsedSpace() + partition->size();
+                    partition_size = std::max(std::min(kMinimumSize, partition_size - margin_size),
+                                              partition_size / 2);
+                    if (!builder->ResizePartition(partition, partition_size)) {
+                        LERROR << "resize " << partition_name;
+                        return false;
+                    }
                 }
-                if (!partition_create) DestroyLogicalPartition(partition_name, 10s);
+                if (!partition_create) DestroyLogicalPartition(partition_name);
                 changed = true;
                 *partition_exists = false;
             }
@@ -907,15 +976,49 @@
     }
 
     if (changed || partition_create) {
-        if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s,
-                                    scratch_device))
+        CreateLogicalPartitionParams params = {
+                .block_device = super_device,
+                .metadata_slot = slot_number,
+                .partition_name = partition_name,
+                .force_writable = true,
+                .timeout_ms = 10s,
+        };
+        if (!CreateLogicalPartition(params, scratch_device)) {
             return false;
+        }
 
         if (change) *change = true;
     }
     return true;
 }
 
+static bool CanUseSuperPartition(const Fstab& fstab) {
+    auto slot_number = fs_mgr_overlayfs_slot_number();
+    auto super_device = fs_mgr_overlayfs_super_device(slot_number);
+    if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) {
+        return false;
+    }
+    return true;
+}
+
+bool fs_mgr_overlayfs_create_scratch(const Fstab& fstab, std::string* scratch_device,
+                                     bool* partition_exists, bool* change) {
+    // Try a physical partition first.
+    *scratch_device = GetPhysicalScratchDevice();
+    if (!scratch_device->empty() && fs_mgr_rw_access(*scratch_device)) {
+        *partition_exists = true;
+        return true;
+    }
+
+    // If that fails, see if we can land on super.
+    if (CanUseSuperPartition(fstab)) {
+        return CreateDynamicScratch(scratch_device, partition_exists, change);
+    }
+
+    errno = ENXIO;
+    return false;
+}
+
 // Create and mount kScratchMountPoint storage if we have logical partitions
 bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab, bool* change) {
     if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
@@ -1004,6 +1107,30 @@
     return candidates;
 }
 
+static void TryMountScratch() {
+    // Note we get the boot scratch device here, which means if scratch was
+    // just created through ImageManager, this could fail. In practice this
+    // should not happen because "remount" detects this scenario (by checking
+    // if verity is still disabled, i.e. no reboot occurred), and skips calling
+    // fs_mgr_overlayfs_mount_all().
+    auto scratch_device = GetBootScratchDevice();
+    if (!fs_mgr_overlayfs_scratch_can_be_mounted(scratch_device)) {
+        return;
+    }
+    if (!WaitForFile(scratch_device, 10s)) {
+        return;
+    }
+    const auto mount_type = fs_mgr_overlayfs_scratch_mount_type();
+    if (!fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type, true /* readonly */)) {
+        return;
+    }
+    auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
+    fs_mgr_overlayfs_umount_scratch();
+    if (has_overlayfs_dir) {
+        fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type);
+    }
+}
+
 bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
     auto ret = false;
     if (fs_mgr_overlayfs_invalid()) return ret;
@@ -1018,19 +1145,7 @@
         }
         if (scratch_can_be_mounted) {
             scratch_can_be_mounted = false;
-            auto scratch_device = fs_mgr_overlayfs_scratch_device();
-            if (fs_mgr_overlayfs_scratch_can_be_mounted(scratch_device) &&
-                fs_mgr_wait_for_file(scratch_device, 10s)) {
-                const auto mount_type = fs_mgr_overlayfs_scratch_mount_type();
-                if (fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type,
-                                                   true /* readonly */)) {
-                    auto has_overlayfs_dir = fs_mgr_access(kScratchMountPoint + kOverlayTopDir);
-                    fs_mgr_overlayfs_umount_scratch();
-                    if (has_overlayfs_dir) {
-                        fs_mgr_overlayfs_mount_scratch(scratch_device, mount_type);
-                    }
-                }
-            }
+            TryMountScratch();
         }
         if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
     }
@@ -1044,11 +1159,23 @@
         return {};
     }
 
+    bool want_scratch = false;
     for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
-        if (fs_mgr_is_verity_enabled(entry)) continue;
-        if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) continue;
-        auto device = fs_mgr_overlayfs_scratch_device();
-        if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break;
+        if (fs_mgr_is_verity_enabled(entry)) {
+            continue;
+        }
+        if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) {
+            continue;
+        }
+        want_scratch = true;
+        break;
+    }
+    if (!want_scratch) {
+        return {};
+    }
+
+    auto device = GetBootScratchDevice();
+    if (!device.empty()) {
         return {device};
     }
     return {};
@@ -1119,25 +1246,57 @@
     return ret;
 }
 
+static bool GetAndMapScratchDeviceIfNeeded(std::string* device, bool* mapped) {
+    *mapped = false;
+    *device = GetBootScratchDevice();
+    if (!device->empty()) {
+        return true;
+    }
+
+    // Avoid uart spam by first checking for a scratch partition.
+    auto metadata_slot = fs_mgr_overlayfs_slot_number();
+    auto super_device = fs_mgr_overlayfs_super_device(metadata_slot);
+    auto metadata = ReadCurrentMetadata(super_device);
+    if (!metadata) {
+        return false;
+    }
+
+    auto partition_name = android::base::Basename(kScratchMountPoint);
+    auto partition = FindPartition(*metadata.get(), partition_name);
+    if (!partition) {
+        return false;
+    }
+
+    CreateLogicalPartitionParams params = {
+            .block_device = super_device,
+            .metadata = metadata.get(),
+            .partition = partition,
+            .force_writable = true,
+            .timeout_ms = 10s,
+    };
+    if (!CreateLogicalPartition(params, device)) {
+        return false;
+    }
+    *mapped = true;
+    return true;
+}
+
 // Returns false if teardown not permitted, errno set to last error.
 // If something is altered, set *change.
 bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
     if (change) *change = false;
     auto ret = true;
+
     // If scratch exists, but is not mounted, lets gain access to clean
     // specific override entries.
     auto mount_scratch = false;
+    bool unmap = false;
     if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
-        auto scratch_device = fs_mgr_overlayfs_scratch_device();
-        if (scratch_device.empty()) {
-            auto slot_number = fs_mgr_overlayfs_slot_number();
-            auto super_device = fs_mgr_overlayfs_super_device(slot_number);
-            const auto partition_name = android::base::Basename(kScratchMountPoint);
-            CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s,
-                                   &scratch_device);
+        std::string scratch_device;
+        if (GetAndMapScratchDeviceIfNeeded(&scratch_device, &unmap)) {
+            mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
+                                                           fs_mgr_overlayfs_scratch_mount_type());
         }
-        mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
-                                                       fs_mgr_overlayfs_scratch_mount_type());
     }
     for (const auto& overlay_mount_point : kOverlayMountPoints) {
         ret &= fs_mgr_overlayfs_teardown_one(
@@ -1156,8 +1315,12 @@
         PERROR << "teardown";
         ret = false;
     }
-    if (mount_scratch) fs_mgr_overlayfs_umount_scratch();
-
+    if (mount_scratch) {
+        fs_mgr_overlayfs_umount_scratch();
+    }
+    if (unmap) {
+        DestroyLogicalPartition(android::base::Basename(kScratchMountPoint));
+    }
     return ret;
 }
 
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 70abf5b..c5e477c 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -88,26 +88,19 @@
 
 using namespace std::chrono_literals;
 
-enum class FileWaitMode { Exists, DoesNotExist };
-
-bool fs_mgr_wait_for_file(const std::string& filename,
-                          const std::chrono::milliseconds relative_timeout,
-                          FileWaitMode wait_mode = FileWaitMode::Exists);
-
 bool fs_mgr_set_blk_ro(const std::string& blockdev, bool readonly = true);
 bool fs_mgr_update_for_slotselect(android::fs_mgr::Fstab* fstab);
 bool fs_mgr_is_device_unlocked();
 const std::string& get_android_dt_dir();
 bool is_dt_compatible();
-int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode);
 
 bool fs_mgr_is_ext4(const std::string& blk_device);
 bool fs_mgr_is_f2fs(const std::string& blk_device);
 
-bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab, bool wait);
+bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab);
 
 namespace android {
 namespace fs_mgr {
-bool UnmapDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
+bool UnmapDevice(const std::string& name);
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 967631b..93bba68 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -82,36 +82,28 @@
 
 void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
               const char* file, unsigned int line, const char* message) {
-    static const char log_characters[] = "VD\0WEFF";
-    if (severity < sizeof(log_characters)) {
-        auto severity_char = log_characters[severity];
-        if (severity_char) fprintf(stderr, "%c ", severity_char);
-    }
     fprintf(stderr, "%s\n", message);
-
     static auto logd = android::base::LogdLogger();
     logd(id, severity, tag, file, line, message);
 }
 
-[[noreturn]] void reboot(bool dedupe) {
-    if (dedupe) {
-        LOG(INFO) << "The device will now reboot to recovery and attempt un-deduplication.";
+[[noreturn]] void reboot(bool overlayfs = false) {
+    if (overlayfs) {
+        LOG(INFO) << "Successfully setup overlayfs\nrebooting device";
     } else {
         LOG(INFO) << "Successfully disabled verity\nrebooting device";
     }
     ::sync();
-    android::base::SetProperty(ANDROID_RB_PROPERTY, dedupe ? "reboot,recovery" : "reboot,remount");
+    android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,remount");
     ::sleep(60);
     ::exit(0);  // SUCCESS
 }
 
 }  // namespace
 
-int main(int argc, char* argv[]) {
-    android::base::InitLogging(argv, MyLogger);
-
+static int do_remount(int argc, char* argv[]) {
     enum {
-        SUCCESS,
+        SUCCESS = 0,
         NOT_USERDEBUG,
         BADARG,
         NOT_ROOT,
@@ -165,7 +157,7 @@
 
     // Make sure we are root.
     if (::getuid() != 0) {
-        LOG(ERROR) << "must be run as root";
+        LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
         return NOT_ROOT;
     }
 
@@ -249,48 +241,38 @@
 
     // Check verity and optionally setup overlayfs backing.
     auto reboot_later = false;
-    auto uses_overlayfs = fs_mgr_overlayfs_valid() != OverlayfsValidResult::kNotSupported;
+    auto user_please_reboot_later = false;
+    auto setup_overlayfs = false;
     auto just_disabled_verity = false;
     for (auto it = partitions.begin(); it != partitions.end();) {
         auto& entry = *it;
         auto& mount_point = entry.mount_point;
         if (fs_mgr_is_verity_enabled(entry)) {
             retval = VERITY_PARTITION;
+            auto ret = false;
             if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") != "locked") {
                 if (AvbOps* ops = avb_ops_user_new()) {
-                    auto ret = avb_user_verity_set(
+                    ret = avb_user_verity_set(
                             ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
                             false);
                     avb_ops_user_free(ops);
-                    if (ret) {
-                        LOG(WARNING) << "Disabling verity for " << mount_point;
-                        just_disabled_verity = true;
-                        reboot_later = can_reboot;
-                        if (reboot_later) {
-                            // w/o overlayfs available, also check for dedupe
-                            if (!uses_overlayfs) {
-                                ++it;
-                                continue;
-                            }
-                            reboot(false);
-                        }
-                    } else if (fs_mgr_set_blk_ro(entry.blk_device, false)) {
-                        fec::io fh(entry.blk_device.c_str(), O_RDWR);
-                        if (fh && fh.set_verity_status(false)) {
-                            LOG(WARNING) << "Disabling verity for " << mount_point;
-                            just_disabled_verity = true;
-                            reboot_later = can_reboot;
-                            if (reboot_later && !uses_overlayfs) {
-                                ++it;
-                                continue;
-                            }
-                        }
-                    }
+                }
+                if (!ret && fs_mgr_set_blk_ro(entry.blk_device, false)) {
+                    fec::io fh(entry.blk_device.c_str(), O_RDWR);
+                    ret = fh && fh.set_verity_status(false);
+                }
+                if (ret) {
+                    LOG(WARNING) << "Disabling verity for " << mount_point;
+                    just_disabled_verity = true;
+                    reboot_later = can_reboot;
+                    user_please_reboot_later = true;
                 }
             }
-            LOG(ERROR) << "Skipping " << mount_point;
-            it = partitions.erase(it);
-            continue;
+            if (!ret) {
+                LOG(ERROR) << "Skipping " << mount_point << " for remount";
+                it = partitions.erase(it);
+                continue;
+            }
         }
 
         auto change = false;
@@ -298,6 +280,9 @@
         if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, just_disabled_verity)) {
             if (change) {
                 LOG(INFO) << "Using overlayfs for " << mount_point;
+                reboot_later = can_reboot;
+                user_please_reboot_later = true;
+                setup_overlayfs = true;
             }
         } else if (errno) {
             PLOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
@@ -308,8 +293,12 @@
         ++it;
     }
 
-    if (partitions.empty()) {
-        if (reboot_later) reboot(false);
+    if (partitions.empty() || just_disabled_verity) {
+        if (reboot_later) reboot(setup_overlayfs);
+        if (user_please_reboot_later) {
+            LOG(INFO) << "Now reboot your device for settings to take effect";
+            return 0;
+        }
         LOG(WARNING) << "No partitions to remount";
         return retval;
     }
@@ -385,7 +374,18 @@
         retval = REMOUNT_FAILED;
     }
 
-    if (reboot_later) reboot(false);
+    if (reboot_later) reboot(setup_overlayfs);
+    if (user_please_reboot_later) {
+        LOG(INFO) << "Now reboot your device for settings to take effect";
+        return 0;
+    }
 
     return retval;
 }
+
+int main(int argc, char* argv[]) {
+    android::base::InitLogging(argv, MyLogger);
+    int result = do_remount(argc, argv);
+    printf("remount %s\n", result ? "failed" : "succeeded");
+    return result;
+}
diff --git a/fs_mgr/fs_mgr_roots.cpp b/fs_mgr/fs_mgr_roots.cpp
index 58ef9b6..1e65587 100644
--- a/fs_mgr/fs_mgr_roots.cpp
+++ b/fs_mgr/fs_mgr_roots.cpp
@@ -101,7 +101,9 @@
         }
     }
 
-    auto mounted = GetMountState(rec->mount_point);
+    const std::string mount_point = mount_pt.empty() ? rec->mount_point : mount_pt;
+
+    auto mounted = GetMountState(mount_point);
     if (mounted == MountState::ERROR) {
         return false;
     }
@@ -109,8 +111,6 @@
         return true;
     }
 
-    const std::string mount_point = mount_pt.empty() ? rec->mount_point : mount_pt;
-
     static const std::vector<std::string> supported_fs{"ext4", "squashfs", "vfat", "f2fs", "none"};
     if (std::find(supported_fs.begin(), supported_fs.end(), rec->fs_type) == supported_fs.end()) {
         LERROR << "unknown fs_type \"" << rec->fs_type << "\" for " << mount_point;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 3f09157..efa2180 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -35,6 +35,7 @@
 #include <android-base/unique_fd.h>
 #include <crypto_utils/android_pubkey.h>
 #include <cutils/properties.h>
+#include <fs_mgr/file_wait.h>
 #include <libdm/dm.h>
 #include <logwrap/logwrap.h>
 #include <openssl/obj_mac.h>
@@ -275,248 +276,6 @@
     return 0;
 }
 
-static int check_verity_restart(const char *fname)
-{
-    char buffer[VERITY_KMSG_BUFSIZE + 1];
-    int fd;
-    int rc = 0;
-    ssize_t size;
-    struct stat s;
-
-    fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
-
-    if (fd == -1) {
-        if (errno != ENOENT) {
-            PERROR << "Failed to open " << fname;
-        }
-        goto out;
-    }
-
-    if (fstat(fd, &s) == -1) {
-        PERROR << "Failed to fstat " << fname;
-        goto out;
-    }
-
-    size = VERITY_KMSG_BUFSIZE;
-
-    if (size > s.st_size) {
-        size = s.st_size;
-    }
-
-    if (lseek(fd, s.st_size - size, SEEK_SET) == -1) {
-        PERROR << "Failed to lseek " << (intmax_t)(s.st_size - size) << " " << fname;
-        goto out;
-    }
-
-    if (!android::base::ReadFully(fd, buffer, size)) {
-        PERROR << "Failed to read " << size << " bytes from " << fname;
-        goto out;
-    }
-
-    buffer[size] = '\0';
-
-    if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) {
-        rc = 1;
-    }
-
-out:
-    if (fd != -1) {
-        close(fd);
-    }
-
-    return rc;
-}
-
-static int was_verity_restart()
-{
-    static const char* files[] = {
-        // clang-format off
-        "/sys/fs/pstore/console-ramoops-0",
-        "/sys/fs/pstore/console-ramoops",
-        "/proc/last_kmsg",
-        NULL
-        // clang-format on
-    };
-    int i;
-
-    for (i = 0; files[i]; ++i) {
-        if (check_verity_restart(files[i])) {
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-static int metadata_add(FILE *fp, long start, const char *tag,
-        unsigned int length, off64_t *offset)
-{
-    if (fseek(fp, start, SEEK_SET) < 0 ||
-        fprintf(fp, "%s %u\n", tag, length) < 0) {
-        return -1;
-    }
-
-    *offset = ftell(fp);
-
-    if (fseek(fp, length, SEEK_CUR) < 0 ||
-        fprintf(fp, METADATA_EOD " 0\n") < 0) {
-        return -1;
-    }
-
-    return 0;
-}
-
-static int metadata_find(const char *fname, const char *stag,
-        unsigned int slength, off64_t *offset)
-{
-    char tag[METADATA_TAG_MAX_LENGTH + 1];
-    int rc = -1;
-    int n;
-    long start = 0x4000; /* skip cryptfs metadata area */
-    uint32_t magic;
-    unsigned int length = 0;
-
-    if (!fname) {
-        return -1;
-    }
-
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fname, "re+"), fclose};
-
-    if (!fp) {
-        PERROR << "Failed to open " << fname;
-        return -1;
-    }
-
-    /* check magic */
-    if (fseek(fp.get(), start, SEEK_SET) < 0 || fread(&magic, sizeof(magic), 1, fp.get()) != 1) {
-        PERROR << "Failed to read magic from " << fname;
-        return -1;
-    }
-
-    if (magic != METADATA_MAGIC) {
-        magic = METADATA_MAGIC;
-
-        if (fseek(fp.get(), start, SEEK_SET) < 0 ||
-            fwrite(&magic, sizeof(magic), 1, fp.get()) != 1) {
-            PERROR << "Failed to write magic to " << fname;
-            return -1;
-        }
-
-        rc = metadata_add(fp.get(), start + sizeof(magic), stag, slength, offset);
-        if (rc < 0) {
-            PERROR << "Failed to add metadata to " << fname;
-        }
-
-        return rc;
-    }
-
-    start += sizeof(magic);
-
-    while (1) {
-        n = fscanf(fp.get(), "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", tag, &length);
-
-        if (n == 2 && strcmp(tag, METADATA_EOD)) {
-            /* found a tag */
-            start = ftell(fp.get());
-
-            if (!strcmp(tag, stag) && length == slength) {
-                *offset = start;
-                return 0;
-            }
-
-            start += length;
-
-            if (fseek(fp.get(), length, SEEK_CUR) < 0) {
-                PERROR << "Failed to seek " << fname;
-                return -1;
-            }
-        } else {
-            rc = metadata_add(fp.get(), start, stag, slength, offset);
-            if (rc < 0) {
-                PERROR << "Failed to write metadata to " << fname;
-            }
-            return rc;
-        }
-    }
-}
-
-static int write_verity_state(const char *fname, off64_t offset, int32_t mode)
-{
-    int fd;
-    int rc = -1;
-    struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode };
-
-    fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC));
-
-    if (fd == -1) {
-        PERROR << "Failed to open " << fname;
-        goto out;
-    }
-
-    if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
-        PERROR << "Failed to write " << sizeof(s) << " bytes to " << fname
-               << " to offset " << offset;
-        goto out;
-    }
-
-    rc = 0;
-
-out:
-    if (fd != -1) {
-        close(fd);
-    }
-
-    return rc;
-}
-
-static int read_verity_state(const char *fname, off64_t offset, int *mode)
-{
-    int fd = -1;
-    int rc = -1;
-    struct verity_state s;
-
-    fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC));
-
-    if (fd == -1) {
-        PERROR << "Failed to open " << fname;
-        goto out;
-    }
-
-    if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) {
-        PERROR << "Failed to read " <<  sizeof(s) << " bytes from " << fname
-               << " offset " << offset;
-        goto out;
-    }
-
-    if (s.header != VERITY_STATE_HEADER) {
-        /* space allocated, but no state written. write default state */
-        *mode = VERITY_MODE_DEFAULT;
-        rc = write_verity_state(fname, offset, *mode);
-        goto out;
-    }
-
-    if (s.version != VERITY_STATE_VERSION) {
-        LERROR << "Unsupported verity state version (" << s.version << ")";
-        goto out;
-    }
-
-    if (s.mode < VERITY_MODE_EIO ||
-        s.mode > VERITY_MODE_LAST) {
-        LERROR << "Unsupported verity mode (" << s.mode << ")";
-        goto out;
-    }
-
-    *mode = s.mode;
-    rc = 0;
-
-out:
-    if (fd != -1) {
-        close(fd);
-    }
-
-    return rc;
-}
-
 static int read_partition(const char *path, uint64_t size)
 {
     char buf[READ_BUF_SIZE];
@@ -540,119 +299,23 @@
     return 0;
 }
 
-static int compare_last_signature(const FstabEntry& entry, int* match) {
-    char tag[METADATA_TAG_MAX_LENGTH + 1];
-    int fd = -1;
-    int rc = -1;
-    off64_t offset = 0;
-    struct fec_handle *f = NULL;
-    struct fec_verity_metadata verity;
-    uint8_t curr[SHA256_DIGEST_LENGTH];
-    uint8_t prev[SHA256_DIGEST_LENGTH];
-
-    *match = 1;
-
-    if (fec_open(&f, entry.blk_device.c_str(), O_RDONLY, FEC_VERITY_DISABLE, FEC_DEFAULT_ROOTS) ==
-        -1) {
-        PERROR << "Failed to open '" << entry.blk_device << "'";
-        return rc;
-    }
-
-    // read verity metadata
-    if (fec_verity_get_metadata(f, &verity) == -1) {
-        PERROR << "Failed to get verity metadata '" << entry.blk_device << "'";
-        goto out;
-    }
-
-    SHA256(verity.signature, sizeof(verity.signature), curr);
-
-    if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s", basename(entry.mount_point.c_str())) >=
-        (int)sizeof(tag)) {
-        LERROR << "Metadata tag name too long for " << entry.mount_point;
-        goto out;
-    }
-
-    if (metadata_find(entry.verity_loc.c_str(), tag, SHA256_DIGEST_LENGTH, &offset) < 0) {
-        goto out;
-    }
-
-    fd = TEMP_FAILURE_RETRY(open(entry.verity_loc.c_str(), O_RDWR | O_SYNC | O_CLOEXEC));
-
-    if (fd == -1) {
-        PERROR << "Failed to open " << entry.verity_loc;
-        goto out;
-    }
-
-    if (TEMP_FAILURE_RETRY(pread64(fd, prev, sizeof(prev), offset)) != sizeof(prev)) {
-        PERROR << "Failed to read " << sizeof(prev) << " bytes from " << entry.verity_loc
-               << " offset " << offset;
-        goto out;
-    }
-
-    *match = !memcmp(curr, prev, SHA256_DIGEST_LENGTH);
-
-    if (!*match) {
-        /* update current signature hash */
-        if (TEMP_FAILURE_RETRY(pwrite64(fd, curr, sizeof(curr),
-                offset)) != sizeof(curr)) {
-            PERROR << "Failed to write " << sizeof(curr) << " bytes to " << entry.verity_loc
-                   << " offset " << offset;
-            goto out;
-        }
-    }
-
-    rc = 0;
-
-out:
-    fec_close(f);
-    return rc;
-}
-
-static int get_verity_state_offset(const FstabEntry& entry, off64_t* offset) {
-    char tag[METADATA_TAG_MAX_LENGTH + 1];
-
-    if (snprintf(tag, sizeof(tag), VERITY_STATE_TAG "_%s", basename(entry.mount_point.c_str())) >=
-        (int)sizeof(tag)) {
-        LERROR << "Metadata tag name too long for " << entry.mount_point;
-        return -1;
-    }
-
-    return metadata_find(entry.verity_loc.c_str(), tag, sizeof(struct verity_state), offset);
-}
-
-int load_verity_state(const FstabEntry& entry, int* mode) {
+bool fs_mgr_load_verity_state(int* mode) {
     // unless otherwise specified, use EIO mode.
     *mode = VERITY_MODE_EIO;
 
-    // use the kernel parameter if set.
-    std::string veritymode;
-    if (fs_mgr_get_boot_config("veritymode", &veritymode)) {
-        if (veritymode == "enforcing") {
-            *mode = VERITY_MODE_DEFAULT;
-        }
-        return 0;
+    // The bootloader communicates verity mode via the kernel commandline
+    std::string verity_mode;
+    if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
+        return false;
     }
 
-    off64_t offset = 0;
-    if (get_verity_state_offset(entry, &offset) < 0) {
-        /* fall back to stateless behavior */
-        return 0;
-    }
-
-    if (was_verity_restart()) {
-        /* device was restarted after dm-verity detected a corrupted
-         * block, so use EIO mode */
-        return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
-    }
-
-    int match = 0;
-    if (!compare_last_signature(entry, &match) && !match) {
-        /* partition has been reflashed, reset dm-verity state */
+    if (verity_mode == "enforcing") {
         *mode = VERITY_MODE_DEFAULT;
-        return write_verity_state(entry.verity_loc.c_str(), offset, *mode);
+    } else if (verity_mode == "logging") {
+        *mode = VERITY_MODE_LOGGING;
     }
 
-    return read_verity_state(entry.verity_loc.c_str(), offset, mode);
+    return true;
 }
 
 // Update the verity table using the actual block device path.
@@ -759,7 +422,7 @@
 
     params.ecc_dev = entry->blk_device.c_str();
 
-    if (load_verity_state(*entry, &params.mode) < 0) {
+    if (!fs_mgr_load_verity_state(&params.mode)) {
         /* if accessing or updating the state failed, switch to the default
          * safe mode. This makes sure the device won't end up in an endless
          * restart loop, and no corrupted data will be exposed to userspace
@@ -867,7 +530,7 @@
     }
 
     // make sure we've set everything up properly
-    if (wait_for_verity_dev && !fs_mgr_wait_for_file(entry->blk_device, 1s)) {
+    if (wait_for_verity_dev && !WaitForFile(entry->blk_device, 1s)) {
         goto out;
     }
 
@@ -884,9 +547,9 @@
     return retval;
 }
 
-bool fs_mgr_teardown_verity(FstabEntry* entry, bool wait) {
+bool fs_mgr_teardown_verity(FstabEntry* entry) {
     const std::string mount_point(basename(entry->mount_point.c_str()));
-    if (!android::fs_mgr::UnmapDevice(mount_point, wait ? 1000ms : 0ms)) {
+    if (!android::fs_mgr::UnmapDevice(mount_point)) {
         return false;
     }
     LINFO << "Unmapped verity device " << mount_point;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index bdec7be..9bc38f9 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -46,7 +46,9 @@
 enum mount_mode {
     MOUNT_MODE_DEFAULT = 0,
     MOUNT_MODE_EARLY = 1,
-    MOUNT_MODE_LATE = 2
+    MOUNT_MODE_LATE = 2,
+    // TODO(b/135984674): remove this after refactoring fs_mgr_mount_all.
+    MOUNT_MODE_ONLY_USERDATA = 3
 };
 
 #define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
@@ -105,6 +107,8 @@
 // it destroys verity devices from device mapper after the device is unmounted.
 int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab);
 
+int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab);
+
 // Finds the dm_bow device on which this block device is stacked, or returns
 // empty string
 std::string fs_mgr_find_bow_device(const std::string& block_device);
diff --git a/fs_mgr/include/fs_mgr/file_wait.h b/fs_mgr/include/fs_mgr/file_wait.h
new file mode 100644
index 0000000..74d160e
--- /dev/null
+++ b/fs_mgr/include/fs_mgr/file_wait.h
@@ -0,0 +1,34 @@
+// 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 <chrono>
+#include <string>
+
+namespace android {
+namespace fs_mgr {
+
+// Wait at most |relative_timeout| milliseconds for |path| to exist. dirname(path)
+// must already exist. For example, to wait on /dev/block/dm-6, /dev/block must
+// be a valid directory.
+bool WaitForFile(const std::string& path, const std::chrono::milliseconds relative_timeout);
+
+// Wait at most |relative_timeout| milliseconds for |path| to stop existing.
+// Note that this only returns true if the inode itself no longer exists, i.e.,
+// all outstanding file descriptors have been closed.
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds relative_timeout);
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/include/fs_mgr_dm_linear.h b/fs_mgr/include/fs_mgr_dm_linear.h
index f33fc02..f3d09fb 100644
--- a/fs_mgr/include/fs_mgr_dm_linear.h
+++ b/fs_mgr/include/fs_mgr_dm_linear.h
@@ -29,6 +29,7 @@
 
 #include <chrono>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -49,26 +50,62 @@
 // method for ReadMetadata and CreateLogicalPartitions.
 bool CreateLogicalPartitions(const std::string& block_device);
 
-// Create a block device for a single logical partition, given metadata and
-// the partition name. On success, a path to the partition's block device is
-// returned. If |force_writable| is true, the "readonly" flag will be ignored
-// so the partition can be flashed.
-//
-// If |timeout_ms| is non-zero, then CreateLogicalPartition will block for the
-// given amount of time until the path returned in |path| is available.
-bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
-                            const std::string& partition_name, bool force_writable,
-                            const std::chrono::milliseconds& timeout_ms, std::string* path);
+struct CreateLogicalPartitionParams {
+    // Block device of the super partition.
+    std::string block_device;
 
-// Same as above, but with a given metadata object. Care should be taken that
-// the metadata represents a valid partition layout.
-bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
-                            const std::string& partition_name, bool force_writable,
-                            const std::chrono::milliseconds& timeout_ms, std::string* path);
+    // If |metadata| is null, the slot will be read using |metadata_slot|.
+    const LpMetadata* metadata = nullptr;
+    std::optional<uint32_t> metadata_slot;
+
+    // If |partition| is not set, it will be found via |partition_name|.
+    const LpMetadataPartition* partition = nullptr;
+    std::string partition_name;
+
+    // Force the device to be read-write even if it was specified as readonly
+    // in the metadata.
+    bool force_writable = false;
+
+    // If |timeout_ms| is non-zero, then CreateLogicalPartition will block for
+    // the given amount of time until the path returned in |path| is available.
+    std::chrono::milliseconds timeout_ms = {};
+
+    // If this is non-empty, it will override the device mapper name (by
+    // default the partition name will be used).
+    std::string device_name;
+
+    // If non-null, this will use the specified IPartitionOpener rather than
+    // the default one.
+    const IPartitionOpener* partition_opener = nullptr;
+
+    // Helpers for determining the effective partition and device name.
+    std::string GetPartitionName() const;
+    std::string GetDeviceName() const;
+
+    // Specify ownership of fields. The ownership of these fields are managed
+    // by the caller of InitDefaults().
+    // These are not declared in CreateLogicalPartitionParams so that the
+    // copy constructor is not deleted.
+    struct OwnedData {
+        std::unique_ptr<LpMetadata> metadata;
+        std::unique_ptr<IPartitionOpener> partition_opener;
+    };
+
+    // Fill in default values for |params| that CreateLogicalPartition assumes. Caller does
+    // not need to call this before calling CreateLogicalPartition; CreateLogicalPartition sets
+    // values when they are missing.
+    // Caller is responsible for destroying owned_data when |this| is not used.
+    bool InitDefaults(OwnedData* owned);
+};
+
+bool CreateLogicalPartition(CreateLogicalPartitionParams params, std::string* path);
 
 // Destroy the block device for a logical partition, by name. If |timeout_ms|
 // is non-zero, then this will block until the device path has been unlinked.
-bool DestroyLogicalPartition(const std::string& name, const std::chrono::milliseconds& timeout_ms);
+bool DestroyLogicalPartition(const std::string& name);
+
+// Helper for populating a DmTable for a logical partition.
+bool CreateDmTable(CreateLogicalPartitionParams params, android::dm::DmTable* table);
 
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index d7afed6..80deaef 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -38,7 +38,6 @@
     std::string fs_options;
     std::string key_loc;
     std::string key_dir;
-    std::string verity_loc;
     off64_t length = 0;
     std::string label;
     int partnum = -1;
@@ -46,8 +45,7 @@
     int max_comp_streams = 0;
     off64_t zram_size = 0;
     off64_t reserved_size = 0;
-    std::string file_contents_mode;
-    std::string file_names_mode;
+    std::string encryption_options;
     off64_t erase_blk_size = 0;
     off64_t logical_blk_size = 0;
     std::string sysfs_path;
@@ -102,9 +100,19 @@
 bool SkipMountingPartitions(Fstab* fstab);
 
 FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
+// The Fstab can contain multiple entries for the same mount point with different configurations.
+std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path);
+FstabEntry* GetMountedEntryForUserdata(Fstab* fstab);
 
-// Helper method to build a GSI fstab entry for mounting /system.
-FstabEntry BuildGsiSystemFstabEntry();
+// This method builds DSU fstab entries and transfer the fstab.
+//
+// fstab points to the unmodified fstab.
+//
+// dsu_partitions contains partition names, e.g.
+//     dsu_partitions[0] = "system_gsi"
+//     dsu_partitions[1] = "userdata_gsi"
+//     dsu_partitions[2] = ...
+void TransformFstabForDsu(Fstab* fstab, const std::vector<std::string>& dsu_partitions);
 
 std::set<std::string> GetBootDevices();
 
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index c8c2d83..8a924d5 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -27,8 +27,12 @@
         "dm_target.cpp",
         "dm.cpp",
         "loop_control.cpp",
+        "utility.cpp",
     ],
 
+    static_libs: [
+        "libext2_uuid",
+    ],
     header_libs: [
         "libbase_headers",
         "liblog_headers",
@@ -40,17 +44,54 @@
     },
 }
 
-cc_test {
-    name: "libdm_test",
-    defaults: ["fs_mgr_defaults"],
-    static_libs: [
-        "libdm",
-        "libbase",
-        "liblog",
-    ],
+filegroup {
+    name: "libdm_test_srcs",
     srcs: [
         "dm_test.cpp",
         "loop_control_test.cpp",
         "test_util.cpp",
-    ]
+    ],
+}
+
+cc_defaults {
+    name: "libdm_defaults",
+    defaults: ["fs_mgr_defaults"],
+    static_libs: [
+        "libdm",
+        "libbase",
+        "libext2_uuid",
+        "libfs_mgr",
+        "liblog",
+    ],
+    srcs: [":libdm_test_srcs"],
+}
+
+cc_test {
+    name: "libdm_test",
+    defaults: ["libdm_defaults"],
+}
+
+cc_test {
+    name: "vts_libdm_test",
+    defaults: ["libdm_defaults"],
+    test_suites: ["vts-core"],
+    auto_gen_config: true,
+    require_root: true,
+    test_min_api_level: 29,
+}
+
+cc_fuzz {
+  name: "dm_linear_table_fuzzer",
+  defaults: ["fs_mgr_defaults"],
+  srcs: [
+    "dm_linear_fuzzer.cpp",
+    "test_util.cpp",
+  ],
+  static_libs: [
+        "libdm",
+        "libbase",
+        "libext2_uuid",
+        "libfs_mgr",
+        "liblog",
+  ],
 }
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index a4614d0..254fbed 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -16,16 +16,29 @@
 
 #include "libdm/dm.h"
 
+#include <linux/dm-ioctl.h>
 #include <sys/ioctl.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
 
+#include <chrono>
+#include <functional>
+#include <string_view>
+#include <thread>
+
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/strings.h>
+#include <uuid/uuid.h>
+
+#include "utility.h"
 
 namespace android {
 namespace dm {
 
+using namespace std::literals;
+
 DeviceMapper::DeviceMapper() : fd_(-1) {
     fd_ = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
     if (fd_ < 0) {
@@ -37,13 +50,13 @@
     static DeviceMapper instance;
     return instance;
 }
+
 // Creates a new device mapper device
-bool DeviceMapper::CreateDevice(const std::string& name) {
+bool DeviceMapper::CreateDevice(const std::string& name, const std::string& uuid) {
     if (name.empty()) {
         LOG(ERROR) << "Unnamed device mapper device creation is not supported";
         return false;
     }
-
     if (name.size() >= DM_NAME_LEN) {
         LOG(ERROR) << "[" << name << "] is too long to be device mapper name";
         return false;
@@ -51,6 +64,9 @@
 
     struct dm_ioctl io;
     InitIo(&io, name);
+    if (!uuid.empty()) {
+        snprintf(io.uuid, sizeof(io.uuid), "%s", uuid.c_str());
+    }
 
     if (ioctl(fd_, DM_DEV_CREATE, &io)) {
         PLOG(ERROR) << "DM_DEV_CREATE failed for [" << name << "]";
@@ -66,17 +82,24 @@
     return true;
 }
 
-bool DeviceMapper::DeleteDevice(const std::string& name) {
-    if (name.empty()) {
-        LOG(ERROR) << "Unnamed device mapper device creation is not supported";
-        return false;
+bool DeviceMapper::DeleteDeviceIfExists(const std::string& name,
+                                        const std::chrono::milliseconds& timeout_ms) {
+    if (GetState(name) == DmDeviceState::INVALID) {
+        return true;
     }
+    return DeleteDevice(name, timeout_ms);
+}
 
-    if (name.size() >= DM_NAME_LEN) {
-        LOG(ERROR) << "[" << name << "] is too long to be device mapper name";
-        return false;
+bool DeviceMapper::DeleteDeviceIfExists(const std::string& name) {
+    return DeleteDeviceIfExists(name, 0ms);
+}
+
+bool DeviceMapper::DeleteDevice(const std::string& name,
+                                const std::chrono::milliseconds& timeout_ms) {
+    std::string unique_path;
+    if (!GetDeviceUniquePath(name, &unique_path)) {
+        LOG(ERROR) << "Failed to get unique path for device " << name;
     }
-
     struct dm_ioctl io;
     InitIo(&io, name);
 
@@ -90,12 +113,84 @@
     CHECK(io.flags & DM_UEVENT_GENERATED_FLAG)
             << "Didn't generate uevent for [" << name << "] removal";
 
+    if (timeout_ms <= std::chrono::milliseconds::zero()) {
+        return true;
+    }
+    if (unique_path.empty()) {
+        return false;
+    }
+    if (!WaitForFileDeleted(unique_path, timeout_ms)) {
+        LOG(ERROR) << "Timeout out waiting for " << unique_path << " to be deleted";
+        return false;
+    }
     return true;
 }
 
-const std::unique_ptr<DmTable> DeviceMapper::table(const std::string& /* name */) const {
-    // TODO(b/110035986): Return the table, as read from the kernel instead
-    return nullptr;
+bool DeviceMapper::DeleteDevice(const std::string& name) {
+    return DeleteDevice(name, 0ms);
+}
+
+static std::string GenerateUuid() {
+    uuid_t uuid_bytes;
+    uuid_generate(uuid_bytes);
+
+    char uuid_chars[37] = {};
+    uuid_unparse_lower(uuid_bytes, uuid_chars);
+
+    return std::string{uuid_chars};
+}
+
+bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table, std::string* path,
+                                const std::chrono::milliseconds& timeout_ms) {
+    std::string uuid = GenerateUuid();
+    if (!CreateDevice(name, uuid)) {
+        return false;
+    }
+
+    // We use the unique path for testing whether the device is ready. After
+    // that, it's safe to use the dm-N path which is compatible with callers
+    // that expect it to be formatted as such.
+    std::string unique_path;
+    if (!LoadTableAndActivate(name, table) || !GetDeviceUniquePath(name, &unique_path) ||
+        !GetDmDevicePathByName(name, path)) {
+        DeleteDevice(name);
+        return false;
+    }
+
+    if (timeout_ms <= std::chrono::milliseconds::zero()) {
+        return true;
+    }
+    if (!WaitForFile(unique_path, timeout_ms)) {
+        LOG(ERROR) << "Timed out waiting for device path: " << unique_path;
+        DeleteDevice(name);
+        return false;
+    }
+    return true;
+}
+
+bool DeviceMapper::GetDeviceUniquePath(const std::string& name, std::string* path) {
+    struct dm_ioctl io;
+    InitIo(&io, name);
+    if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
+        PLOG(ERROR) << "Failed to get device path: " << name;
+        return false;
+    }
+
+    if (io.uuid[0] == '\0') {
+        LOG(ERROR) << "Device does not have a unique path: " << name;
+        return false;
+    }
+    *path = "/dev/block/mapper/by-uuid/"s + io.uuid;
+    return true;
+}
+
+std::optional<DeviceMapper::Info> DeviceMapper::GetDetailedInfo(const std::string& name) const {
+    struct dm_ioctl io;
+    InitIo(&io, name);
+    if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
+        return std::nullopt;
+    }
+    return Info(io.flags);
 }
 
 DmDeviceState DeviceMapper::GetState(const std::string& name) const {
@@ -110,12 +205,27 @@
     return DmDeviceState::SUSPENDED;
 }
 
-bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) {
-    if (!CreateDevice(name)) {
+bool DeviceMapper::ChangeState(const std::string& name, DmDeviceState state) {
+    if (state != DmDeviceState::SUSPENDED && state != DmDeviceState::ACTIVE) {
         return false;
     }
-    if (!LoadTableAndActivate(name, table)) {
-        DeleteDevice(name);
+
+    struct dm_ioctl io;
+    InitIo(&io, name);
+
+    if (state == DmDeviceState::SUSPENDED) io.flags = DM_SUSPEND_FLAG;
+
+    if (ioctl(fd_, DM_DEV_SUSPEND, &io) < 0) {
+        PLOG(ERROR) << "DM_DEV_SUSPEND "
+                    << (state == DmDeviceState::SUSPENDED ? "suspend" : "resume") << " failed";
+        return false;
+    }
+    return true;
+}
+
+bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) {
+    std::string ignore_path;
+    if (!CreateDevice(name, table, &ignore_path, 0ms)) {
         return false;
     }
     return true;
@@ -210,6 +320,20 @@
     return true;
 }
 
+bool DeviceMapper::GetTargetByName(const std::string& name, DmTargetTypeInfo* info) {
+    std::vector<DmTargetTypeInfo> targets;
+    if (!GetAvailableTargets(&targets)) {
+        return false;
+    }
+    for (const auto& target : targets) {
+        if (target.name() == name) {
+            if (info) *info = target;
+            return true;
+        }
+    }
+    return false;
+}
+
 bool DeviceMapper::GetAvailableDevices(std::vector<DmBlockDevice>* devices) {
     devices->clear();
 
@@ -288,6 +412,26 @@
     return true;
 }
 
+bool DeviceMapper::GetDeviceNumber(const std::string& name, dev_t* dev) {
+    struct dm_ioctl io;
+    InitIo(&io, name);
+    if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
+        PLOG(WARNING) << "DM_DEV_STATUS failed for " << name;
+        return false;
+    }
+    *dev = io.dev;
+    return true;
+}
+
+bool DeviceMapper::GetDeviceString(const std::string& name, std::string* dev) {
+    dev_t num;
+    if (!GetDeviceNumber(name, &num)) {
+        return false;
+    }
+    *dev = std::to_string(major(num)) + ":" + std::to_string(minor(num));
+    return true;
+}
+
 bool DeviceMapper::GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
     return GetTable(name, 0, table);
 }
@@ -354,5 +498,86 @@
     }
 }
 
+std::string DeviceMapper::GetTargetType(const struct dm_target_spec& spec) {
+    if (const void* p = memchr(spec.target_type, '\0', sizeof(spec.target_type))) {
+        ptrdiff_t length = reinterpret_cast<const char*>(p) - spec.target_type;
+        return std::string{spec.target_type, static_cast<size_t>(length)};
+    }
+    return std::string{spec.target_type, sizeof(spec.target_type)};
+}
+
+static bool ExtractBlockDeviceName(const std::string& path, std::string* name) {
+    static constexpr std::string_view kDevBlockPrefix("/dev/block/");
+    if (android::base::StartsWith(path, kDevBlockPrefix)) {
+        *name = path.substr(kDevBlockPrefix.length());
+        return true;
+    }
+    return false;
+}
+
+bool DeviceMapper::IsDmBlockDevice(const std::string& path) {
+    std::string name;
+    if (!ExtractBlockDeviceName(path, &name)) {
+        return false;
+    }
+    return android::base::StartsWith(name, "dm-");
+}
+
+std::optional<std::string> DeviceMapper::GetDmDeviceNameByPath(const std::string& path) {
+    std::string name;
+    if (!ExtractBlockDeviceName(path, &name)) {
+        LOG(WARNING) << path << " is not a block device";
+        return std::nullopt;
+    }
+    if (!android::base::StartsWith(name, "dm-")) {
+        LOG(WARNING) << path << " is not a dm device";
+        return std::nullopt;
+    }
+    std::string dm_name_file = "/sys/block/" + name + "/dm/name";
+    std::string dm_name;
+    if (!android::base::ReadFileToString(dm_name_file, &dm_name)) {
+        PLOG(ERROR) << "Failed to read file " << dm_name_file;
+        return std::nullopt;
+    }
+    dm_name = android::base::Trim(dm_name);
+    return dm_name;
+}
+
+std::optional<std::string> DeviceMapper::GetParentBlockDeviceByPath(const std::string& path) {
+    std::string name;
+    if (!ExtractBlockDeviceName(path, &name)) {
+        LOG(WARNING) << path << " is not a block device";
+        return std::nullopt;
+    }
+    if (!android::base::StartsWith(name, "dm-")) {
+        // Reached bottom of the device mapper stack.
+        return std::nullopt;
+    }
+    auto slaves_dir = "/sys/block/" + name + "/slaves";
+    auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(slaves_dir.c_str()), closedir);
+    if (dir == nullptr) {
+        PLOG(ERROR) << "Failed to open: " << slaves_dir;
+        return std::nullopt;
+    }
+    std::string sub_device_name = "";
+    for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
+        if (entry->d_type != DT_LNK) continue;
+        if (!sub_device_name.empty()) {
+            LOG(ERROR) << "Too many slaves in " << slaves_dir;
+            return std::nullopt;
+        }
+        sub_device_name = entry->d_name;
+    }
+    if (sub_device_name.empty()) {
+        LOG(ERROR) << "No slaves in " << slaves_dir;
+        return std::nullopt;
+    }
+    return "/dev/block/" + sub_device_name;
+}
+
+bool DeviceMapper::TargetInfo::IsOverflowSnapshot() const {
+    return spec.target_type == "snapshot"s && data == "Overflow"s;
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/dm_linear_fuzzer.cpp b/fs_mgr/libdm/dm_linear_fuzzer.cpp
new file mode 100644
index 0000000..8462901
--- /dev/null
+++ b/fs_mgr/libdm/dm_linear_fuzzer.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <chrono>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <libdm/dm_table.h>
+#include <libdm/loop_control.h>
+
+#include "test_util.h"
+
+using namespace android;
+using namespace android::base;
+using namespace android::dm;
+using namespace std;
+using namespace std::chrono_literals;
+
+/*
+ * This test aims at making the library crash, so these functions are not
+ * really useful.
+ * Keeping them here for future use.
+ */
+template <class T, class C>
+void ASSERT_EQ(const T& /*a*/, const C& /*b*/) {
+    // if (a != b) {}
+}
+
+template <class T>
+void ASSERT_FALSE(const T& /*a*/) {
+    // if (a) {}
+}
+
+template <class T, class C>
+void ASSERT_GE(const T& /*a*/, const C& /*b*/) {
+    // if (a < b) {}
+}
+
+template <class T, class C>
+void ASSERT_NE(const T& /*a*/, const C& /*b*/) {
+    // if (a == b) {}
+}
+
+template <class T>
+void ASSERT_TRUE(const T& /*a*/) {
+    // if (!a) {}
+}
+
+template <class T, class C>
+void EXPECT_EQ(const T& a, const C& b) {
+    ASSERT_EQ(a, b);
+}
+
+template <class T>
+void EXPECT_TRUE(const T& a) {
+    ASSERT_TRUE(a);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    uint64_t val[6];
+
+    if (size != sizeof(val)) {
+        return 0;
+    }
+
+    memcpy(&val, &data[0], sizeof(*val));
+
+    unique_fd tmp1(CreateTempFile("file_1", 4096));
+    ASSERT_GE(tmp1, 0);
+    unique_fd tmp2(CreateTempFile("file_2", 4096));
+    ASSERT_GE(tmp2, 0);
+
+    LoopDevice loop_a(tmp1, 10s);
+    ASSERT_TRUE(loop_a.valid());
+    LoopDevice loop_b(tmp2, 10s);
+    ASSERT_TRUE(loop_b.valid());
+
+    // Define a 2-sector device, with each sector mapping to the first sector
+    // of one of our loop devices.
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[0], val[1], loop_a.device(), val[2]));
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(val[3], val[4], loop_b.device(), val[5]));
+    ASSERT_TRUE(table.valid());
+    ASSERT_EQ(2u, table.num_sectors());
+
+    TempDevice dev("libdm-test-dm-linear", table);
+    ASSERT_TRUE(dev.valid());
+    ASSERT_FALSE(dev.path().empty());
+
+    auto& dm = DeviceMapper::Instance();
+
+    dev_t dev_number;
+    ASSERT_TRUE(dm.GetDeviceNumber(dev.name(), &dev_number));
+    ASSERT_NE(dev_number, 0);
+
+    std::string dev_string;
+    ASSERT_TRUE(dm.GetDeviceString(dev.name(), &dev_string));
+    ASSERT_FALSE(dev_string.empty());
+
+    // Test GetTableStatus.
+    vector<DeviceMapper::TargetInfo> targets;
+    ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
+    ASSERT_EQ(targets.size(), 2);
+    EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
+    EXPECT_TRUE(targets[0].data.empty());
+    EXPECT_EQ(targets[0].spec.sector_start, 0);
+    EXPECT_EQ(targets[0].spec.length, 1);
+    EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
+    EXPECT_TRUE(targets[1].data.empty());
+    EXPECT_EQ(targets[1].spec.sector_start, 1);
+    EXPECT_EQ(targets[1].spec.length, 1);
+
+    // Test GetTargetType().
+    EXPECT_EQ(DeviceMapper::GetTargetType(targets[0].spec), std::string{"linear"});
+    EXPECT_EQ(DeviceMapper::GetTargetType(targets[1].spec), std::string{"linear"});
+
+    // Normally the TestDevice destructor would delete this, but at least one
+    // test should ensure that device deletion works.
+    ASSERT_TRUE(dev.Destroy());
+
+    return 0;
+}
diff --git a/fs_mgr/libdm/dm_table.cpp b/fs_mgr/libdm/dm_table.cpp
index 15c7ce1..efe03ab 100644
--- a/fs_mgr/libdm/dm_table.cpp
+++ b/fs_mgr/libdm/dm_table.cpp
@@ -26,6 +26,7 @@
     if (!target->Valid()) {
         return false;
     }
+    num_sectors_ += target->size();
     targets_.push_back(std::move(target));
     return true;
 }
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index cb33eea..65f6e12 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -16,8 +16,13 @@
 
 #include "libdm/dm_target.h"
 
+#include <inttypes.h>
+#include <stdio.h>
+#include <sys/types.h>
+
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/parseint.h>
 #include <android-base/strings.h>
 
 #include <libdm/dm.h>
@@ -115,5 +120,133 @@
     return keyid_ + " " + block_device_;
 }
 
+std::string DmTargetSnapshot::name() const {
+    if (mode_ == SnapshotStorageMode::Merge) {
+        return "snapshot-merge";
+    }
+    return "snapshot";
+}
+
+std::string DmTargetSnapshot::GetParameterString() const {
+    std::string mode;
+    switch (mode_) {
+        case SnapshotStorageMode::Persistent:
+        case SnapshotStorageMode::Merge:
+            // Note: "O" lets us query for overflow in the status message. This
+            // is only supported on kernels 4.4+. On earlier kernels, an overflow
+            // will be reported as "Invalid" in the status string.
+            mode = "P";
+            if (ReportsOverflow(name())) {
+                mode += "O";
+            }
+            break;
+        case SnapshotStorageMode::Transient:
+            mode = "N";
+            break;
+        default:
+            LOG(ERROR) << "DmTargetSnapshot unknown mode";
+            break;
+    }
+    return base_device_ + " " + cow_device_ + " " + mode + " " + std::to_string(chunk_size_);
+}
+
+// Computes the percentage of complition for snapshot status.
+// @sectors_initial is the number of sectors_allocated stored right before
+// starting the merge.
+double DmTargetSnapshot::MergePercent(const DmTargetSnapshot::Status& status,
+                                      uint64_t sectors_initial) {
+    uint64_t s = status.sectors_allocated;
+    uint64_t t = status.total_sectors;
+    uint64_t m = status.metadata_sectors;
+    uint64_t i = sectors_initial == 0 ? t : sectors_initial;
+
+    if (t <= s || i <= s) {
+        return 0.0;
+    }
+    if (s == 0 || t == 0 || s <= m) {
+        return 100.0;
+    }
+    return 100.0 / (i - m) * (i - s);
+}
+
+bool DmTargetSnapshot::ReportsOverflow(const std::string& target_type) {
+    DeviceMapper& dm = DeviceMapper::Instance();
+    DmTargetTypeInfo info;
+    if (!dm.GetTargetByName(target_type, &info)) {
+        return false;
+    }
+    if (target_type == "snapshot") {
+        return info.IsAtLeast(1, 15, 0);
+    }
+    if (target_type == "snapshot-merge") {
+        return info.IsAtLeast(1, 4, 0);
+    }
+    return false;
+}
+
+bool DmTargetSnapshot::ParseStatusText(const std::string& text, Status* status) {
+    // Try to parse the line as it should be
+    int args = sscanf(text.c_str(), "%" PRIu64 "/%" PRIu64 " %" PRIu64, &status->sectors_allocated,
+                      &status->total_sectors, &status->metadata_sectors);
+    if (args == 3) {
+        return true;
+    }
+    auto sections = android::base::Split(text, " ");
+    if (sections.size() == 0) {
+        LOG(ERROR) << "could not parse empty status";
+        return false;
+    }
+    // Error codes are: "Invalid", "Overflow" and "Merge failed"
+    if (sections.size() == 1) {
+        if (text == "Invalid" || text == "Overflow") {
+            status->error = text;
+            return true;
+        }
+    } else if (sections.size() == 2 && text == "Merge failed") {
+        status->error = text;
+        return true;
+    }
+    LOG(ERROR) << "could not parse snapshot status: wrong format";
+    return false;
+}
+
+bool DmTargetSnapshot::GetDevicesFromParams(const std::string& params, std::string* base_device,
+                                            std::string* cow_device) {
+    auto pieces = android::base::Split(params, " ");
+    if (pieces.size() < 2) {
+        LOG(ERROR) << "Parameter string is invalid: " << params;
+        return false;
+    }
+    *base_device = pieces[0];
+    *cow_device = pieces[1];
+    return true;
+}
+
+std::string DmTargetCrypt::GetParameterString() const {
+    std::vector<std::string> argv = {
+            cipher_,
+            key_,
+            std::to_string(iv_sector_offset_),
+            device_,
+            std::to_string(device_sector_),
+    };
+
+    std::vector<std::string> extra_argv;
+    if (allow_discards_) extra_argv.emplace_back("allow_discards");
+    if (allow_encrypt_override_) extra_argv.emplace_back("allow_encrypt_override");
+    if (iv_large_sectors_) extra_argv.emplace_back("iv_large_sectors");
+    if (sector_size_) extra_argv.emplace_back("sector_size:" + std::to_string(sector_size_));
+
+    if (!extra_argv.empty()) argv.emplace_back(std::to_string(extra_argv.size()));
+
+    argv.insert(argv.end(), extra_argv.begin(), extra_argv.end());
+    return android::base::Join(argv, " ");
+}
+
+std::string DmTargetDefaultKey::GetParameterString() const {
+    return cipher_ + " " + key_ + " " + blockdev_ + " " + std::to_string(start_sector_) +
+           (set_dun_ ? " 1 set_dun" : "");
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index 70823c6..b7f31bc 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -24,10 +24,12 @@
 
 #include <chrono>
 #include <ctime>
+#include <iostream>
 #include <map>
 #include <thread>
 
 #include <android-base/file.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <gtest/gtest.h>
 #include <libdm/dm.h>
@@ -35,88 +37,17 @@
 #include "test_util.h"
 
 using namespace std;
+using namespace std::chrono_literals;
 using namespace android::dm;
 using unique_fd = android::base::unique_fd;
 
 TEST(libdm, HasMinimumTargets) {
+    DmTargetTypeInfo info;
+
     DeviceMapper& dm = DeviceMapper::Instance();
-    vector<DmTargetTypeInfo> targets;
-    ASSERT_TRUE(dm.GetAvailableTargets(&targets));
-
-    map<string, DmTargetTypeInfo> by_name;
-    for (const auto& target : targets) {
-        by_name[target.name()] = target;
-    }
-
-    auto iter = by_name.find("linear");
-    EXPECT_NE(iter, by_name.end());
+    ASSERT_TRUE(dm.GetTargetByName("linear", &info));
 }
 
-// Helper to ensure that device mapper devices are released.
-class TempDevice {
-  public:
-    TempDevice(const std::string& name, const DmTable& table)
-        : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
-        valid_ = dm_.CreateDevice(name, table);
-    }
-    TempDevice(TempDevice&& other) noexcept
-        : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
-        other.valid_ = false;
-    }
-    ~TempDevice() {
-        if (valid_) {
-            dm_.DeleteDevice(name_);
-        }
-    }
-    bool Destroy() {
-        if (!valid_) {
-            return false;
-        }
-        valid_ = false;
-        return dm_.DeleteDevice(name_);
-    }
-    bool WaitForUdev() const {
-        auto start_time = std::chrono::steady_clock::now();
-        while (true) {
-            if (!access(path().c_str(), F_OK)) {
-                return true;
-            }
-            if (errno != ENOENT) {
-                return false;
-            }
-            std::this_thread::sleep_for(50ms);
-            std::chrono::duration elapsed = std::chrono::steady_clock::now() - start_time;
-            if (elapsed >= 5s) {
-                return false;
-            }
-        }
-    }
-    std::string path() const {
-        std::string device_path;
-        if (!dm_.GetDmDevicePathByName(name_, &device_path)) {
-            return "";
-        }
-        return device_path;
-    }
-    const std::string& name() const { return name_; }
-    bool valid() const { return valid_; }
-
-    TempDevice(const TempDevice&) = delete;
-    TempDevice& operator=(const TempDevice&) = delete;
-
-    TempDevice& operator=(TempDevice&& other) noexcept {
-        name_ = other.name_;
-        valid_ = other.valid_;
-        other.valid_ = false;
-        return *this;
-    }
-
-  private:
-    DeviceMapper& dm_;
-    std::string name_;
-    bool valid_;
-};
-
 TEST(libdm, DmLinear) {
     unique_fd tmp1(CreateTempFile("file_1", 4096));
     ASSERT_GE(tmp1, 0);
@@ -129,22 +60,32 @@
     ASSERT_TRUE(android::base::WriteFully(tmp1, message1, sizeof(message1)));
     ASSERT_TRUE(android::base::WriteFully(tmp2, message2, sizeof(message2)));
 
-    LoopDevice loop_a(tmp1);
+    LoopDevice loop_a(tmp1, 10s);
     ASSERT_TRUE(loop_a.valid());
-    LoopDevice loop_b(tmp2);
+    LoopDevice loop_b(tmp2, 10s);
     ASSERT_TRUE(loop_b.valid());
 
     // Define a 2-sector device, with each sector mapping to the first sector
     // of one of our loop devices.
     DmTable table;
-    ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(0, 1, loop_a.device(), 0)));
-    ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(1, 1, loop_b.device(), 0)));
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop_a.device(), 0));
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(1, 1, loop_b.device(), 0));
     ASSERT_TRUE(table.valid());
+    ASSERT_EQ(2u, table.num_sectors());
 
     TempDevice dev("libdm-test-dm-linear", table);
     ASSERT_TRUE(dev.valid());
     ASSERT_FALSE(dev.path().empty());
-    ASSERT_TRUE(dev.WaitForUdev());
+
+    auto& dm = DeviceMapper::Instance();
+
+    dev_t dev_number;
+    ASSERT_TRUE(dm.GetDeviceNumber(dev.name(), &dev_number));
+    ASSERT_NE(dev_number, 0);
+
+    std::string dev_string;
+    ASSERT_TRUE(dm.GetDeviceString(dev.name(), &dev_string));
+    ASSERT_FALSE(dev_string.empty());
 
     // Note: a scope is needed to ensure that there are no open descriptors
     // when we go to close the device.
@@ -162,7 +103,6 @@
     }
 
     // Test GetTableStatus.
-    DeviceMapper& dm = DeviceMapper::Instance();
     vector<DeviceMapper::TargetInfo> targets;
     ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
     ASSERT_EQ(targets.size(), 2);
@@ -175,11 +115,44 @@
     EXPECT_EQ(targets[1].spec.sector_start, 1);
     EXPECT_EQ(targets[1].spec.length, 1);
 
+    // Test GetTargetType().
+    EXPECT_EQ(DeviceMapper::GetTargetType(targets[0].spec), std::string{"linear"});
+    EXPECT_EQ(DeviceMapper::GetTargetType(targets[1].spec), std::string{"linear"});
+
     // Normally the TestDevice destructor would delete this, but at least one
     // test should ensure that device deletion works.
     ASSERT_TRUE(dev.Destroy());
 }
 
+TEST(libdm, DmSuspendResume) {
+    unique_fd tmp1(CreateTempFile("file_suspend_resume", 512));
+    ASSERT_GE(tmp1, 0);
+
+    LoopDevice loop_a(tmp1, 10s);
+    ASSERT_TRUE(loop_a.valid());
+
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop_a.device(), 0));
+    ASSERT_TRUE(table.valid());
+    ASSERT_EQ(1u, table.num_sectors());
+
+    TempDevice dev("libdm-test-dm-suspend-resume", table);
+    ASSERT_TRUE(dev.valid());
+    ASSERT_FALSE(dev.path().empty());
+
+    auto& dm = DeviceMapper::Instance();
+
+    // Test Set and Get status of device.
+    vector<DeviceMapper::TargetInfo> targets;
+    ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE);
+
+    ASSERT_TRUE(dm.ChangeState(dev.name(), DmDeviceState::SUSPENDED));
+    ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::SUSPENDED);
+
+    ASSERT_TRUE(dm.ChangeState(dev.name(), DmDeviceState::ACTIVE));
+    ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE);
+}
+
 TEST(libdm, DmVerityArgsAvb2) {
     std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a";
     std::string algorithm = "sha1";
@@ -201,3 +174,434 @@
             "2 fec_blocks 126955 fec_start 126955 restart_on_corruption ignore_zero_blocks";
     EXPECT_EQ(target.GetParameterString(), expected);
 }
+
+TEST(libdm, DmSnapshotArgs) {
+    DmTargetSnapshot target1(0, 512, "base", "cow", SnapshotStorageMode::Persistent, 8);
+    if (DmTargetSnapshot::ReportsOverflow("snapshot")) {
+        EXPECT_EQ(target1.GetParameterString(), "base cow PO 8");
+    } else {
+        EXPECT_EQ(target1.GetParameterString(), "base cow P 8");
+    }
+    EXPECT_EQ(target1.name(), "snapshot");
+
+    DmTargetSnapshot target2(0, 512, "base", "cow", SnapshotStorageMode::Transient, 8);
+    EXPECT_EQ(target2.GetParameterString(), "base cow N 8");
+    EXPECT_EQ(target2.name(), "snapshot");
+
+    DmTargetSnapshot target3(0, 512, "base", "cow", SnapshotStorageMode::Merge, 8);
+    if (DmTargetSnapshot::ReportsOverflow("snapshot-merge")) {
+        EXPECT_EQ(target3.GetParameterString(), "base cow PO 8");
+    } else {
+        EXPECT_EQ(target3.GetParameterString(), "base cow P 8");
+    }
+    EXPECT_EQ(target3.name(), "snapshot-merge");
+}
+
+TEST(libdm, DmSnapshotOriginArgs) {
+    DmTargetSnapshotOrigin target(0, 512, "base");
+    EXPECT_EQ(target.GetParameterString(), "base");
+    EXPECT_EQ(target.name(), "snapshot-origin");
+}
+
+class SnapshotTestHarness final {
+  public:
+    bool Setup();
+    bool Merge();
+
+    std::string origin_dev() const { return origin_dev_->path(); }
+    std::string snapshot_dev() const { return snapshot_dev_->path(); }
+
+    int base_fd() const { return base_fd_; }
+
+    static const uint64_t kBaseDeviceSize = 1024 * 1024;
+    static const uint64_t kCowDeviceSize = 1024 * 64;
+    static const uint64_t kSectorSize = 512;
+
+  private:
+    void SetupImpl();
+    void MergeImpl();
+
+    unique_fd base_fd_;
+    unique_fd cow_fd_;
+    unique_ptr<LoopDevice> base_loop_;
+    unique_ptr<LoopDevice> cow_loop_;
+    unique_ptr<TempDevice> origin_dev_;
+    unique_ptr<TempDevice> snapshot_dev_;
+    bool setup_ok_ = false;
+    bool merge_ok_ = false;
+};
+
+bool SnapshotTestHarness::Setup() {
+    SetupImpl();
+    return setup_ok_;
+}
+
+void SnapshotTestHarness::SetupImpl() {
+    base_fd_ = CreateTempFile("base_device", kBaseDeviceSize);
+    ASSERT_GE(base_fd_, 0);
+    cow_fd_ = CreateTempFile("cow_device", kCowDeviceSize);
+    ASSERT_GE(cow_fd_, 0);
+
+    base_loop_ = std::make_unique<LoopDevice>(base_fd_, 10s);
+    ASSERT_TRUE(base_loop_->valid());
+    cow_loop_ = std::make_unique<LoopDevice>(cow_fd_, 10s);
+    ASSERT_TRUE(cow_loop_->valid());
+
+    DmTable origin_table;
+    ASSERT_TRUE(origin_table.AddTarget(make_unique<DmTargetSnapshotOrigin>(
+            0, kBaseDeviceSize / kSectorSize, base_loop_->device())));
+    ASSERT_TRUE(origin_table.valid());
+    ASSERT_EQ(kBaseDeviceSize / kSectorSize, origin_table.num_sectors());
+
+    origin_dev_ = std::make_unique<TempDevice>("libdm-test-dm-snapshot-origin", origin_table);
+    ASSERT_TRUE(origin_dev_->valid());
+    ASSERT_FALSE(origin_dev_->path().empty());
+
+    // chunk size = 4K blocks.
+    DmTable snap_table;
+    ASSERT_TRUE(snap_table.AddTarget(make_unique<DmTargetSnapshot>(
+            0, kBaseDeviceSize / kSectorSize, base_loop_->device(), cow_loop_->device(),
+            SnapshotStorageMode::Persistent, 8)));
+    ASSERT_TRUE(snap_table.valid());
+    ASSERT_EQ(kBaseDeviceSize / kSectorSize, snap_table.num_sectors());
+
+    snapshot_dev_ = std::make_unique<TempDevice>("libdm-test-dm-snapshot", snap_table);
+    ASSERT_TRUE(snapshot_dev_->valid());
+    ASSERT_FALSE(snapshot_dev_->path().empty());
+
+    setup_ok_ = true;
+}
+
+bool SnapshotTestHarness::Merge() {
+    MergeImpl();
+    return merge_ok_;
+}
+
+void SnapshotTestHarness::MergeImpl() {
+    DmTable merge_table;
+    ASSERT_TRUE(merge_table.AddTarget(
+            make_unique<DmTargetSnapshot>(0, kBaseDeviceSize / kSectorSize, base_loop_->device(),
+                                          cow_loop_->device(), SnapshotStorageMode::Merge, 8)));
+    ASSERT_TRUE(merge_table.valid());
+    ASSERT_EQ(kBaseDeviceSize / kSectorSize, merge_table.num_sectors());
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    ASSERT_TRUE(dm.LoadTableAndActivate("libdm-test-dm-snapshot", merge_table));
+
+    while (true) {
+        vector<DeviceMapper::TargetInfo> status;
+        ASSERT_TRUE(dm.GetTableStatus("libdm-test-dm-snapshot", &status));
+        ASSERT_EQ(status.size(), 1);
+        ASSERT_EQ(strncmp(status[0].spec.target_type, "snapshot-merge", strlen("snapshot-merge")),
+                  0);
+
+        DmTargetSnapshot::Status merge_status;
+        ASSERT_TRUE(DmTargetSnapshot::ParseStatusText(status[0].data, &merge_status));
+        ASSERT_TRUE(merge_status.error.empty());
+        if (merge_status.sectors_allocated == merge_status.metadata_sectors) {
+            break;
+        }
+
+        std::this_thread::sleep_for(250ms);
+    }
+
+    merge_ok_ = true;
+}
+
+bool CheckSnapshotAvailability() {
+    DmTargetTypeInfo info;
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.GetTargetByName("snapshot", &info)) {
+        cout << "snapshot module not enabled; skipping test" << std::endl;
+        return false;
+    }
+    if (!dm.GetTargetByName("snapshot-merge", &info)) {
+        cout << "snapshot-merge module not enabled; skipping test" << std::endl;
+        return false;
+    }
+    if (!dm.GetTargetByName("snapshot-origin", &info)) {
+        cout << "snapshot-origin module not enabled; skipping test" << std::endl;
+        return false;
+    }
+    return true;
+}
+
+TEST(libdm, DmSnapshot) {
+    if (!CheckSnapshotAvailability()) {
+        return;
+    }
+
+    SnapshotTestHarness harness;
+    ASSERT_TRUE(harness.Setup());
+
+    // Open the dm devices.
+    unique_fd origin_fd(open(harness.origin_dev().c_str(), O_RDONLY | O_CLOEXEC));
+    ASSERT_GE(origin_fd, 0);
+    unique_fd snapshot_fd(open(harness.snapshot_dev().c_str(), O_RDWR | O_CLOEXEC | O_SYNC));
+    ASSERT_GE(snapshot_fd, 0);
+
+    // Write to the first block of the snapshot device.
+    std::string data("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
+    ASSERT_TRUE(android::base::WriteFully(snapshot_fd, data.data(), data.size()));
+    ASSERT_EQ(lseek(snapshot_fd, 0, SEEK_SET), 0);
+
+    // We should get the same data back from the snapshot device.
+    std::string read(data.size(), '\0');
+    ASSERT_TRUE(android::base::ReadFully(snapshot_fd, read.data(), read.size()));
+    ASSERT_EQ(read, data);
+
+    // We should see the original data from the origin device.
+    std::string zeroes(data.size(), '\0');
+    ASSERT_TRUE(android::base::ReadFully(origin_fd, read.data(), read.size()));
+    ASSERT_EQ(lseek(snapshot_fd, 0, SEEK_SET), 0);
+    ASSERT_EQ(read, zeroes);
+
+    // We should also see the original data from the base device.
+    ASSERT_TRUE(android::base::ReadFully(harness.base_fd(), read.data(), read.size()));
+    ASSERT_EQ(lseek(harness.base_fd(), 0, SEEK_SET), 0);
+    ASSERT_EQ(read, zeroes);
+
+    // Now, perform the merge and wait.
+    ASSERT_TRUE(harness.Merge());
+
+    // Reading from the base device should give us the modified data.
+    ASSERT_TRUE(android::base::ReadFully(harness.base_fd(), read.data(), read.size()));
+    ASSERT_EQ(lseek(harness.base_fd(), 0, SEEK_SET), 0);
+    ASSERT_EQ(read, data);
+}
+
+TEST(libdm, DmSnapshotOverflow) {
+    if (!CheckSnapshotAvailability()) {
+        return;
+    }
+
+    SnapshotTestHarness harness;
+    ASSERT_TRUE(harness.Setup());
+
+    // Open the dm devices.
+    unique_fd snapshot_fd(open(harness.snapshot_dev().c_str(), O_RDWR | O_CLOEXEC));
+    ASSERT_GE(snapshot_fd, 0);
+
+    // Fill the copy-on-write device until it overflows.
+    uint64_t bytes_remaining = SnapshotTestHarness::kCowDeviceSize;
+    uint8_t byte = 1;
+    while (bytes_remaining) {
+        std::string data(4096, char(byte));
+        if (!android::base::WriteFully(snapshot_fd, data.data(), data.size())) {
+            ASSERT_EQ(errno, EIO);
+            break;
+        }
+        bytes_remaining -= data.size();
+    }
+
+    // If writes succeed (because they are buffered), then we should expect an
+    // fsync to fail with EIO.
+    if (!bytes_remaining) {
+        ASSERT_EQ(fsync(snapshot_fd), -1);
+        ASSERT_EQ(errno, EIO);
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+
+    vector<DeviceMapper::TargetInfo> target_status;
+    ASSERT_TRUE(dm.GetTableStatus("libdm-test-dm-snapshot", &target_status));
+    ASSERT_EQ(target_status.size(), 1);
+    ASSERT_EQ(strncmp(target_status[0].spec.target_type, "snapshot", strlen("snapshot")), 0);
+
+    DmTargetSnapshot::Status status;
+    ASSERT_TRUE(DmTargetSnapshot::ParseStatusText(target_status[0].data, &status));
+    if (DmTargetSnapshot::ReportsOverflow("snapshot")) {
+        ASSERT_EQ(status.error, "Overflow");
+    } else {
+        ASSERT_EQ(status.error, "Invalid");
+    }
+}
+
+TEST(libdm, ParseStatusText) {
+    DmTargetSnapshot::Status status;
+
+    // Bad inputs
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("X", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123/456", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123 456", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123 456", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123 456 789", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123 456/789", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123/456/789", &status));
+    EXPECT_FALSE(DmTargetSnapshot::ParseStatusText("123 / 456 789", &status));
+
+    // Good input
+    EXPECT_TRUE(DmTargetSnapshot::ParseStatusText("123/456 789", &status));
+    EXPECT_EQ(status.sectors_allocated, 123);
+    EXPECT_EQ(status.total_sectors, 456);
+    EXPECT_EQ(status.metadata_sectors, 789);
+
+    // Known error codes
+    EXPECT_TRUE(DmTargetSnapshot::ParseStatusText("Invalid", &status));
+    EXPECT_TRUE(DmTargetSnapshot::ParseStatusText("Merge failed", &status));
+    EXPECT_TRUE(DmTargetSnapshot::ParseStatusText("Overflow", &status));
+}
+
+TEST(libdm, DmSnapshotMergePercent) {
+    DmTargetSnapshot::Status status;
+
+    // Correct input
+    status.sectors_allocated = 1000;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 0;
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status), 1.0);
+
+    status.sectors_allocated = 500;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 0;
+    EXPECT_GE(DmTargetSnapshot::MergePercent(status), 49.0);
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status), 51.0);
+
+    status.sectors_allocated = 0;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 0;
+    EXPECT_GE(DmTargetSnapshot::MergePercent(status), 99.0);
+
+    status.sectors_allocated = 500;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 500;
+    EXPECT_GE(DmTargetSnapshot::MergePercent(status), 99.0);
+
+    status.sectors_allocated = 500;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 0;
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status, 500), 1.0);
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status, 1000), 51.0);
+    EXPECT_GE(DmTargetSnapshot::MergePercent(status, 1000), 49.0);
+
+    // Robustness
+    status.sectors_allocated = 2000;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 0;
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status), 0.0);
+
+    status.sectors_allocated = 2000;
+    status.total_sectors = 1000;
+    status.metadata_sectors = 2000;
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status), 0.0);
+
+    status.sectors_allocated = 2000;
+    status.total_sectors = 0;
+    status.metadata_sectors = 2000;
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status), 0.0);
+
+    status.sectors_allocated = 1000;
+    status.total_sectors = 0;
+    status.metadata_sectors = 1000;
+    EXPECT_LE(DmTargetSnapshot::MergePercent(status, 0), 0.0);
+}
+
+TEST(libdm, CryptArgs) {
+    DmTargetCrypt target1(0, 512, "sha1", "abcdefgh", 50, "/dev/loop0", 100);
+    ASSERT_EQ(target1.name(), "crypt");
+    ASSERT_TRUE(target1.Valid());
+    ASSERT_EQ(target1.GetParameterString(), "sha1 abcdefgh 50 /dev/loop0 100");
+
+    DmTargetCrypt target2(0, 512, "sha1", "abcdefgh", 50, "/dev/loop0", 100);
+    target2.SetSectorSize(64);
+    target2.AllowDiscards();
+    target2.SetIvLargeSectors();
+    target2.AllowEncryptOverride();
+    ASSERT_EQ(target2.GetParameterString(),
+              "sha1 abcdefgh 50 /dev/loop0 100 4 allow_discards allow_encrypt_override "
+              "iv_large_sectors sector_size:64");
+}
+
+TEST(libdm, DefaultKeyArgs) {
+    DmTargetDefaultKey target(0, 4096, "AES-256-XTS", "abcdef0123456789", "/dev/loop0", 0);
+    ASSERT_EQ(target.name(), "default-key");
+    ASSERT_TRUE(target.Valid());
+    ASSERT_EQ(target.GetParameterString(), "AES-256-XTS abcdef0123456789 /dev/loop0 0");
+}
+
+TEST(libdm, DeleteDeviceWithTimeout) {
+    unique_fd tmp(CreateTempFile("file_1", 4096));
+    ASSERT_GE(tmp, 0);
+    LoopDevice loop(tmp, 10s);
+    ASSERT_TRUE(loop.valid());
+
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
+    ASSERT_TRUE(table.valid());
+    TempDevice dev("libdm-test-dm-linear", table);
+    ASSERT_TRUE(dev.valid());
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+
+    std::string path;
+    ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
+    ASSERT_EQ(0, access(path.c_str(), F_OK));
+
+    ASSERT_TRUE(dm.DeleteDevice("libdm-test-dm-linear", 5s));
+    ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
+    ASSERT_NE(0, access(path.c_str(), F_OK));
+    ASSERT_EQ(ENOENT, errno);
+}
+
+TEST(libdm, IsDmBlockDevice) {
+    unique_fd tmp(CreateTempFile("file_1", 4096));
+    ASSERT_GE(tmp, 0);
+    LoopDevice loop(tmp, 10s);
+    ASSERT_TRUE(loop.valid());
+    ASSERT_TRUE(android::base::StartsWith(loop.device(), "/dev/block"));
+
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
+    ASSERT_TRUE(table.valid());
+
+    TempDevice dev("libdm-test-dm-linear", table);
+    ASSERT_TRUE(dev.valid());
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    ASSERT_TRUE(dm.IsDmBlockDevice(dev.path()));
+    ASSERT_FALSE(dm.IsDmBlockDevice(loop.device()));
+}
+
+TEST(libdm, GetDmDeviceNameByPath) {
+    unique_fd tmp(CreateTempFile("file_1", 4096));
+    ASSERT_GE(tmp, 0);
+    LoopDevice loop(tmp, 10s);
+    ASSERT_TRUE(loop.valid());
+    ASSERT_TRUE(android::base::StartsWith(loop.device(), "/dev/block"));
+
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
+    ASSERT_TRUE(table.valid());
+
+    TempDevice dev("libdm-test-dm-linear", table);
+    ASSERT_TRUE(dev.valid());
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    // Not a dm device, GetDmDeviceNameByPath will return std::nullopt.
+    ASSERT_FALSE(dm.GetDmDeviceNameByPath(loop.device()));
+    auto name = dm.GetDmDeviceNameByPath(dev.path());
+    ASSERT_EQ("libdm-test-dm-linear", *name);
+}
+
+TEST(libdm, GetParentBlockDeviceByPath) {
+    unique_fd tmp(CreateTempFile("file_1", 4096));
+    ASSERT_GE(tmp, 0);
+    LoopDevice loop(tmp, 10s);
+    ASSERT_TRUE(loop.valid());
+    ASSERT_TRUE(android::base::StartsWith(loop.device(), "/dev/block"));
+
+    DmTable table;
+    ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
+    ASSERT_TRUE(table.valid());
+
+    TempDevice dev("libdm-test-dm-linear", table);
+    ASSERT_TRUE(dev.valid());
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    ASSERT_FALSE(dm.GetParentBlockDeviceByPath(loop.device()));
+    auto sub_block_device = dm.GetParentBlockDeviceByPath(dev.path());
+    ASSERT_EQ(loop.device(), *sub_block_device);
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 28e6e01..abe9c4c 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -20,11 +20,14 @@
 #include <fcntl.h>
 #include <linux/dm-ioctl.h>
 #include <linux/kdev_t.h>
+#include <linux/types.h>
 #include <stdint.h>
 #include <sys/sysmacros.h>
 #include <unistd.h>
 
+#include <chrono>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -37,13 +40,15 @@
 #define DM_VERSION2 (0)
 
 #define DM_ALIGN_MASK (7)
-#define DM_ALIGN(x) ((x + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
+#define DM_ALIGN(x) (((x) + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
 
 namespace android {
 namespace dm {
 
 enum class DmDeviceState { INVALID, SUSPENDED, ACTIVE };
 
+static constexpr uint64_t kSectorSize = 512;
+
 class DeviceMapper final {
   public:
     class DmBlockDevice final {
@@ -68,21 +73,71 @@
         uint64_t dev_;
     };
 
+    class Info {
+        uint32_t flags_;
+
+      public:
+        explicit Info(uint32_t flags) : flags_(flags) {}
+
+        bool IsActiveTablePresent() const { return flags_ & DM_ACTIVE_PRESENT_FLAG; }
+        bool IsBufferFull() const { return flags_ & DM_BUFFER_FULL_FLAG; }
+        bool IsInactiveTablePresent() const { return flags_ & DM_INACTIVE_PRESENT_FLAG; }
+        bool IsReadOnly() const { return flags_ & DM_READONLY_FLAG; }
+        bool IsSuspended() const { return flags_ & DM_SUSPEND_FLAG; }
+    };
+
     // Removes a device mapper device with the given name.
     // Returns 'true' on success, false otherwise.
     bool DeleteDevice(const std::string& name);
+    bool DeleteDeviceIfExists(const std::string& name);
+    // Removes a device mapper device with the given name and waits for |timeout_ms| milliseconds
+    // for the corresponding block device to be deleted.
+    bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
+    bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms);
 
-    // Reads the device mapper table from the device with given anme and
-    // returns it in a DmTable object.
-    const std::unique_ptr<DmTable> table(const std::string& name) const;
+    // Fetches and returns the complete state of the underlying device mapper
+    // device with given name.
+    std::optional<Info> GetDetailedInfo(const std::string& name) const;
 
     // Returns the current state of the underlying device mapper device
     // with given name.
     // One of INVALID, SUSPENDED or ACTIVE.
     DmDeviceState GetState(const std::string& name) const;
 
+    // Puts the given device to the specified status, which must be either:
+    // - SUSPENDED: suspend the device, or
+    // - ACTIVE: resumes the device.
+    bool ChangeState(const std::string& name, DmDeviceState state);
+
     // Creates a device, loads the given table, and activates it. If the device
     // is not able to be activated, it is destroyed, and false is returned.
+    // After creation, |path| contains the result of calling
+    // GetDmDevicePathByName, and the path is guaranteed to exist. If after
+    // |timeout_ms| the path is not available, the device will be deleted and
+    // this function will return false.
+    //
+    // This variant must be used when depending on the device path. The
+    // following manual sequence should not be used:
+    //
+    //   1. CreateDevice(name, table)
+    //   2. GetDmDevicePathByName(name, &path)
+    //   3. fs_mgr::WaitForFile(path, <timeout>)
+    //
+    // This sequence has a race condition where, if another process deletes a
+    // device, CreateDevice may acquire the same path. When this happens, the
+    // WaitForFile() may early-return since ueventd has not yet processed all
+    // of the outstanding udev events. The caller may unexpectedly get an
+    // ENOENT on a system call using the affected path.
+    //
+    // If |timeout_ms| is 0ms, then this function will return true whether or
+    // not |path| is available. It is the caller's responsibility to ensure
+    // there are no races.
+    bool CreateDevice(const std::string& name, const DmTable& table, std::string* path,
+                      const std::chrono::milliseconds& timeout_ms);
+
+    // Create a device and activate the given table, without waiting to acquire
+    // a valid path. If the caller will use GetDmDevicePathByName(), it should
+    // use the timeout variant above.
     bool CreateDevice(const std::string& name, const DmTable& table);
 
     // Loads the device mapper table from parameter into the underlying device
@@ -96,6 +151,10 @@
     // successfully read and stored in 'targets'. Returns 'false' otherwise.
     bool GetAvailableTargets(std::vector<DmTargetTypeInfo>* targets);
 
+    // Finds a target by name and returns its information if found. |info| may
+    // be null to check for the existence of a target.
+    bool GetTargetByName(const std::string& name, DmTargetTypeInfo* info);
+
     // Return 'true' if it can successfully read the list of device mapper block devices
     // currently created. 'devices' will be empty if the kernel interactions
     // were successful and there are no block devices at the moment. Returns
@@ -105,8 +164,28 @@
     // Returns the path to the device mapper device node in '/dev' corresponding to
     // 'name'. If the device does not exist, false is returned, and the path
     // parameter is not set.
+    //
+    // This returns a path in the format "/dev/block/dm-N" that can be easily
+    // re-used with sysfs.
+    //
+    // WaitForFile() should not be used in conjunction with this call, since it
+    // could race with ueventd.
     bool GetDmDevicePathByName(const std::string& name, std::string* path);
 
+    // Returns a device's unique path as generated by ueventd. This will return
+    // true as long as the device has been created, even if ueventd has not
+    // processed it yet.
+    //
+    // The formatting of this path is /dev/block/mapper/by-uuid/<uuid>.
+    bool GetDeviceUniquePath(const std::string& name, std::string* path);
+
+    // Returns the dev_t for the named device-mapper node.
+    bool GetDeviceNumber(const std::string& name, dev_t* dev);
+
+    // Returns a major:minor string for the named device-mapper node, that can
+    // be used as inputs to DmTargets that take a block device.
+    bool GetDeviceString(const std::string& name, std::string* dev);
+
     // The only way to create a DeviceMapper object.
     static DeviceMapper& Instance();
 
@@ -123,8 +202,11 @@
     struct TargetInfo {
         struct dm_target_spec spec;
         std::string data;
+        TargetInfo() {}
         TargetInfo(const struct dm_target_spec& spec, const std::string& data)
             : spec(spec), data(data) {}
+
+        bool IsOverflowSnapshot() const;
     };
     bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table);
 
@@ -132,6 +214,21 @@
     // mapper device from the kernel.
     bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table);
 
+    static std::string GetTargetType(const struct dm_target_spec& spec);
+
+    // Returns true if given path is a path to a dm block device.
+    bool IsDmBlockDevice(const std::string& path);
+
+    // Returns name of a dm-device with the given path, or std::nulloptr if given path is not a
+    // dm-device.
+    std::optional<std::string> GetDmDeviceNameByPath(const std::string& path);
+
+    // Returns a parent block device of a dm device with the given path, or std::nullopt if:
+    //  * Given path doesn't correspond to a dm device.
+    //  * A dm device is based on top of more than one block devices.
+    //  * A failure occurred.
+    std::optional<std::string> GetParentBlockDeviceByPath(const std::string& path);
+
   private:
     // Maximum possible device mapper targets registered in the kernel.
     // This is only used to read the list of targets from kernel so we allocate
@@ -144,18 +241,12 @@
     // limit we are imposing here of 256.
     static constexpr uint32_t kMaxPossibleDmDevices = 256;
 
+    bool CreateDevice(const std::string& name, const std::string& uuid = {});
     bool GetTable(const std::string& name, uint32_t flags, std::vector<TargetInfo>* table);
-
     void InitIo(struct dm_ioctl* io, const std::string& name = std::string()) const;
 
     DeviceMapper();
 
-    // Creates a device mapper device with given name.
-    // Return 'true' on success and 'false' on failure to
-    // create OR if a device mapper device with the same name already
-    // exists.
-    bool CreateDevice(const std::string& name);
-
     int fd_;
     // Non-copyable & Non-movable
     DeviceMapper(const DeviceMapper&) = delete;
diff --git a/fs_mgr/libdm/include/libdm/dm_table.h b/fs_mgr/libdm/include/libdm/dm_table.h
index 5c639be..ee66653 100644
--- a/fs_mgr/libdm/include/libdm/dm_table.h
+++ b/fs_mgr/libdm/include/libdm/dm_table.h
@@ -43,12 +43,20 @@
     // successfully removed.
     bool RemoveTarget(std::unique_ptr<DmTarget>&& target);
 
+    // Adds a target, constructing it in-place for convenience. For example,
+    //
+    //   table.Emplace<DmTargetZero>(0, num_sectors);
+    template <typename T, typename... Args>
+    bool Emplace(Args&&... args) {
+        return AddTarget(std::make_unique<T>(std::forward<Args>(args)...));
+    }
+
     // Checks the table to make sure it is valid. i.e. Checks for range overlaps, range gaps
     // and returns 'true' if the table is ready to be loaded into kernel. Returns 'false' if the
     // table is malformed.
     bool valid() const;
 
-    // Returns the toatl number of targets.
+    // Returns the total number of targets.
     size_t num_targets() const { return targets_.size(); }
 
     // Returns the total size represented by the table in terms of number of 512-byte sectors.
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 175b0f0..a78bc71 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -40,6 +40,18 @@
         return std::to_string(major_) + "." + std::to_string(minor_) + "." + std::to_string(patch_);
     }
 
+    uint32_t major_version() const { return major_; }
+    uint32_t minor_version() const { return minor_; }
+    uint32_t patch_level() const { return patch_; }
+
+    bool IsAtLeast(uint32_t major, uint32_t minor, uint32_t patch) const {
+        if (major_ > major) return true;
+        if (major_ < major) return false;
+        if (minor_ > minor) return true;
+        if (minor_ < minor) return false;
+        return patch_ >= patch;
+    }
+
   private:
     std::string name_;
     uint32_t major_;
@@ -170,6 +182,125 @@
     std::string target_string_;
 };
 
+enum class SnapshotStorageMode {
+    // The snapshot will be persisted to the COW device.
+    Persistent,
+    // The snapshot will be lost on reboot.
+    Transient,
+    // The snapshot will be merged from the COW device into the base device,
+    // in the background.
+    Merge
+};
+
+// Writes to a snapshot device will be written to the given COW device. Reads
+// will read from the COW device or base device. The chunk size is specified
+// in sectors.
+class DmTargetSnapshot final : public DmTarget {
+  public:
+    DmTargetSnapshot(uint64_t start, uint64_t length, const std::string& base_device,
+                     const std::string& cow_device, SnapshotStorageMode mode, uint64_t chunk_size)
+        : DmTarget(start, length),
+          base_device_(base_device),
+          cow_device_(cow_device),
+          mode_(mode),
+          chunk_size_(chunk_size) {}
+
+    std::string name() const override;
+    std::string GetParameterString() const override;
+    bool Valid() const override { return true; }
+
+    struct Status {
+        uint64_t sectors_allocated;
+        uint64_t total_sectors;
+        uint64_t metadata_sectors;
+        std::string error;
+    };
+
+    static double MergePercent(const Status& status, uint64_t sectors_initial = 0);
+    static bool ParseStatusText(const std::string& text, Status* status);
+    static bool ReportsOverflow(const std::string& target_type);
+    static bool GetDevicesFromParams(const std::string& params, std::string* base_device,
+                                     std::string* cow_device);
+
+  private:
+    std::string base_device_;
+    std::string cow_device_;
+    SnapshotStorageMode mode_;
+    uint64_t chunk_size_;
+};
+
+// snapshot-origin will read/write directly to the backing device, updating any
+// snapshot devices with a matching origin.
+class DmTargetSnapshotOrigin final : public DmTarget {
+  public:
+    DmTargetSnapshotOrigin(uint64_t start, uint64_t length, const std::string& device)
+        : DmTarget(start, length), device_(device) {}
+
+    std::string name() const override { return "snapshot-origin"; }
+    std::string GetParameterString() const override { return device_; }
+    bool Valid() const override { return true; }
+
+  private:
+    std::string device_;
+};
+
+class DmTargetCrypt final : public DmTarget {
+  public:
+    DmTargetCrypt(uint64_t start, uint64_t length, const std::string& cipher,
+                  const std::string& key, uint64_t iv_sector_offset, const std::string& device,
+                  uint64_t device_sector)
+        : DmTarget(start, length),
+          cipher_(cipher),
+          key_(key),
+          iv_sector_offset_(iv_sector_offset),
+          device_(device),
+          device_sector_(device_sector) {}
+
+    void AllowDiscards() { allow_discards_ = true; }
+    void AllowEncryptOverride() { allow_encrypt_override_ = true; }
+    void SetIvLargeSectors() { iv_large_sectors_ = true; }
+    void SetSectorSize(uint32_t sector_size) { sector_size_ = sector_size; }
+
+    std::string name() const override { return "crypt"; }
+    bool Valid() const override { return true; }
+    std::string GetParameterString() const override;
+
+  private:
+    std::string cipher_;
+    std::string key_;
+    uint64_t iv_sector_offset_;
+    std::string device_;
+    uint64_t device_sector_;
+    bool allow_discards_ = false;
+    bool allow_encrypt_override_ = false;
+    bool iv_large_sectors_ = false;
+    uint32_t sector_size_ = 0;
+};
+
+class DmTargetDefaultKey final : public DmTarget {
+  public:
+    DmTargetDefaultKey(uint64_t start, uint64_t length, const std::string& cipher,
+                       const std::string& key, const std::string& blockdev, uint64_t start_sector,
+                       bool set_dun = false)
+        : DmTarget(start, length),
+          cipher_(cipher),
+          key_(key),
+          blockdev_(blockdev),
+          start_sector_(start_sector),
+          set_dun_(set_dun) {}
+
+    std::string name() const override { return "default-key"; }
+    bool Valid() const override { return true; }
+    std::string GetParameterString() const override;
+
+  private:
+    std::string cipher_;
+    std::string key_;
+    std::string blockdev_;
+    uint64_t start_sector_;
+    bool set_dun_;
+};
+
 }  // namespace dm
 }  // namespace android
 
diff --git a/fs_mgr/libdm/include/libdm/loop_control.h b/fs_mgr/libdm/include/libdm/loop_control.h
index e6e83f4..ad53c11 100644
--- a/fs_mgr/libdm/include/libdm/loop_control.h
+++ b/fs_mgr/libdm/include/libdm/loop_control.h
@@ -17,6 +17,7 @@
 #ifndef _LIBDM_LOOP_CONTROL_H_
 #define _LIBDM_LOOP_CONTROL_H_
 
+#include <chrono>
 #include <string>
 
 #include <android-base/unique_fd.h>
@@ -29,12 +30,22 @@
     LoopControl();
 
     // Attaches the file specified by 'file_fd' to the loop device specified
-    // by 'loopdev'
-    bool Attach(int file_fd, std::string* loopdev) const;
+    // by 'loopdev'. It is possible that in between allocating and attaching
+    // a loop device, another process attaches to the chosen loop device. If
+    // this happens, Attach() will retry for up to |timeout_ms|. The timeout
+    // should not be zero.
+    //
+    // The caller does not have to call WaitForFile(); it is implicitly called.
+    // The given |timeout_ms| covers both potential sources of timeout.
+    bool Attach(int file_fd, const std::chrono::milliseconds& timeout_ms,
+                std::string* loopdev) const;
 
     // Detach the loop device given by 'loopdev' from the attached backing file.
     bool Detach(const std::string& loopdev) const;
 
+    // Enable Direct I/O on a loop device. This requires kernel 4.9+.
+    static bool EnableDirectIo(int fd);
+
     LoopControl(const LoopControl&) = delete;
     LoopControl& operator=(const LoopControl&) = delete;
     LoopControl& operator=(LoopControl&&) = default;
@@ -53,13 +64,14 @@
   public:
     // Create a loop device for the given file descriptor. It is closed when
     // LoopDevice is destroyed only if auto_close is true.
-    LoopDevice(int fd, bool auto_close = false);
+    LoopDevice(android::base::borrowed_fd fd, const std::chrono::milliseconds& timeout_ms,
+               bool auto_close = false);
     // Create a loop device for the given file path. It will be opened for
     // reading and writing and closed when the loop device is detached.
-    explicit LoopDevice(const std::string& path);
+    LoopDevice(const std::string& path, const std::chrono::milliseconds& timeout_ms);
     ~LoopDevice();
 
-    bool valid() const { return fd_ != -1 && !device_.empty(); }
+    bool valid() const { return valid_; }
     const std::string& device() const { return device_; }
 
     LoopDevice(const LoopDevice&) = delete;
@@ -68,12 +80,13 @@
     LoopDevice(LoopDevice&&) = default;
 
   private:
-    void Init();
+    void Init(const std::chrono::milliseconds& timeout_ms);
 
-    android::base::unique_fd fd_;
-    bool owns_fd_;
+    android::base::borrowed_fd fd_;
+    android::base::unique_fd owned_fd_;
     std::string device_;
     LoopControl control_;
+    bool valid_ = false;
 };
 
 }  // namespace dm
diff --git a/fs_mgr/libdm/loop_control.cpp b/fs_mgr/libdm/loop_control.cpp
index 0beb1a6..2e40a18 100644
--- a/fs_mgr/libdm/loop_control.cpp
+++ b/fs_mgr/libdm/loop_control.cpp
@@ -27,6 +27,8 @@
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 
+#include "utility.h"
+
 namespace android {
 namespace dm {
 
@@ -37,21 +39,40 @@
     }
 }
 
-bool LoopControl::Attach(int file_fd, std::string* loopdev) const {
-    if (!FindFreeLoopDevice(loopdev)) {
-        LOG(ERROR) << "Failed to attach, no free loop devices";
-        return false;
-    }
+bool LoopControl::Attach(int file_fd, const std::chrono::milliseconds& timeout_ms,
+                         std::string* loopdev) const {
+    auto start_time = std::chrono::steady_clock::now();
+    auto condition = [&]() -> WaitResult {
+        if (!FindFreeLoopDevice(loopdev)) {
+            LOG(ERROR) << "Failed to attach, no free loop devices";
+            return WaitResult::Fail;
+        }
 
-    android::base::unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loopdev->c_str(), O_RDWR | O_CLOEXEC)));
-    if (loop_fd < 0) {
-        PLOG(ERROR) << "Failed to open: " << *loopdev;
-        return false;
-    }
+        auto now = std::chrono::steady_clock::now();
+        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+        if (!WaitForFile(*loopdev, timeout_ms - time_elapsed)) {
+            LOG(ERROR) << "Timed out waiting for path: " << *loopdev;
+            return WaitResult::Fail;
+        }
 
-    int rc = ioctl(loop_fd, LOOP_SET_FD, file_fd);
-    if (rc < 0) {
-        PLOG(ERROR) << "Failed LOOP_SET_FD";
+        android::base::unique_fd loop_fd(
+                TEMP_FAILURE_RETRY(open(loopdev->c_str(), O_RDWR | O_CLOEXEC)));
+        if (loop_fd < 0) {
+            PLOG(ERROR) << "Failed to open: " << *loopdev;
+            return WaitResult::Fail;
+        }
+
+        if (int rc = ioctl(loop_fd, LOOP_SET_FD, file_fd); rc == 0) {
+            return WaitResult::Done;
+        }
+        if (errno != EBUSY) {
+            PLOG(ERROR) << "Failed LOOP_SET_FD";
+            return WaitResult::Fail;
+        }
+        return WaitResult::Wait;
+    };
+    if (!WaitForCondition(condition, timeout_ms)) {
+        LOG(ERROR) << "Timed out trying to acquire a loop device";
         return false;
     }
     return true;
@@ -91,30 +112,55 @@
     return true;
 }
 
-LoopDevice::LoopDevice(int fd, bool auto_close) : fd_(fd), owns_fd_(auto_close) {
-    Init();
+bool LoopControl::EnableDirectIo(int fd) {
+#if !defined(LOOP_SET_BLOCK_SIZE)
+    static constexpr int LOOP_SET_BLOCK_SIZE = 0x4C09;
+#endif
+#if !defined(LOOP_SET_DIRECT_IO)
+    static constexpr int LOOP_SET_DIRECT_IO = 0x4C08;
+#endif
+
+    // Note: the block size has to be >= the logical block size of the underlying
+    // block device, *not* the filesystem block size.
+    if (ioctl(fd, LOOP_SET_BLOCK_SIZE, 4096)) {
+        PLOG(ERROR) << "Could not set loop device block size";
+        return false;
+    }
+    if (ioctl(fd, LOOP_SET_DIRECT_IO, 1)) {
+        PLOG(ERROR) << "Could not set loop direct IO";
+        return false;
+    }
+    return true;
 }
 
-LoopDevice::LoopDevice(const std::string& path) : fd_(-1), owns_fd_(true) {
-    fd_.reset(open(path.c_str(), O_RDWR | O_CLOEXEC));
-    if (fd_ < -1) {
+LoopDevice::LoopDevice(android::base::borrowed_fd fd, const std::chrono::milliseconds& timeout_ms,
+                       bool auto_close)
+    : fd_(fd), owned_fd_(-1) {
+    if (auto_close) {
+        owned_fd_.reset(fd.get());
+    }
+    Init(timeout_ms);
+}
+
+LoopDevice::LoopDevice(const std::string& path, const std::chrono::milliseconds& timeout_ms)
+    : fd_(-1), owned_fd_(-1) {
+    owned_fd_.reset(open(path.c_str(), O_RDWR | O_CLOEXEC));
+    if (owned_fd_ == -1) {
         PLOG(ERROR) << "open failed for " << path;
         return;
     }
-    Init();
+    fd_ = owned_fd_;
+    Init(timeout_ms);
 }
 
 LoopDevice::~LoopDevice() {
     if (valid()) {
         control_.Detach(device_);
     }
-    if (!owns_fd_) {
-        (void)fd_.release();
-    }
 }
 
-void LoopDevice::Init() {
-    control_.Attach(fd_, &device_);
+void LoopDevice::Init(const std::chrono::milliseconds& timeout_ms) {
+    valid_ = control_.Attach(fd_.get(), timeout_ms, &device_);
 }
 
 }  // namespace dm
diff --git a/fs_mgr/libdm/loop_control_test.cpp b/fs_mgr/libdm/loop_control_test.cpp
index 08bdc00..0749f26 100644
--- a/fs_mgr/libdm/loop_control_test.cpp
+++ b/fs_mgr/libdm/loop_control_test.cpp
@@ -53,7 +53,7 @@
     unique_fd fd = TempFile();
     ASSERT_GE(fd, 0);
 
-    LoopDevice loop(fd);
+    LoopDevice loop(fd, 10s);
     ASSERT_TRUE(loop.valid());
 
     char buffer[6];
diff --git a/fs_mgr/libdm/test_util.h b/fs_mgr/libdm/test_util.h
index 96b051c..6671364 100644
--- a/fs_mgr/libdm/test_util.h
+++ b/fs_mgr/libdm/test_util.h
@@ -20,8 +20,12 @@
 #include <android-base/unique_fd.h>
 #include <stddef.h>
 
+#include <chrono>
 #include <string>
 
+#include <libdm/dm.h>
+#include <libdm/dm_table.h>
+
 namespace android {
 namespace dm {
 
@@ -29,6 +33,50 @@
 // created with a fixed size.
 android::base::unique_fd CreateTempFile(const std::string& name, size_t size);
 
+// Helper to ensure that device mapper devices are released.
+class TempDevice {
+  public:
+    TempDevice(const std::string& name, const DmTable& table)
+        : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
+        valid_ = dm_.CreateDevice(name, table, &path_, std::chrono::seconds(5));
+    }
+    TempDevice(TempDevice&& other) noexcept
+        : dm_(other.dm_), name_(other.name_), path_(other.path_), valid_(other.valid_) {
+        other.valid_ = false;
+    }
+    ~TempDevice() {
+        if (valid_) {
+            dm_.DeleteDevice(name_);
+        }
+    }
+    bool Destroy() {
+        if (!valid_) {
+            return false;
+        }
+        valid_ = false;
+        return dm_.DeleteDevice(name_);
+    }
+    std::string path() const { return path_; }
+    const std::string& name() const { return name_; }
+    bool valid() const { return valid_; }
+
+    TempDevice(const TempDevice&) = delete;
+    TempDevice& operator=(const TempDevice&) = delete;
+
+    TempDevice& operator=(TempDevice&& other) noexcept {
+        name_ = other.name_;
+        valid_ = other.valid_;
+        other.valid_ = false;
+        return *this;
+    }
+
+  private:
+    DeviceMapper& dm_;
+    std::string name_;
+    std::string path_;
+    bool valid_;
+};
+
 }  // namespace dm
 }  // namespace android
 
diff --git a/fs_mgr/libdm/utility.cpp b/fs_mgr/libdm/utility.cpp
new file mode 100644
index 0000000..f252565
--- /dev/null
+++ b/fs_mgr/libdm/utility.cpp
@@ -0,0 +1,66 @@
+// 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 "utility.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <thread>
+
+using namespace std::literals;
+
+namespace android {
+namespace dm {
+
+bool WaitForCondition(const std::function<WaitResult()>& condition,
+                      const std::chrono::milliseconds& timeout_ms) {
+    auto start_time = std::chrono::steady_clock::now();
+    while (true) {
+        auto result = condition();
+        if (result == WaitResult::Done) return true;
+        if (result == WaitResult::Fail) return false;
+
+        std::this_thread::sleep_for(20ms);
+
+        auto now = std::chrono::steady_clock::now();
+        auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+        if (time_elapsed > timeout_ms) return false;
+    }
+}
+
+bool WaitForFile(const std::string& path, const std::chrono::milliseconds& timeout_ms) {
+    auto condition = [&]() -> WaitResult {
+        // If the file exists but returns EPERM or something, we consider the
+        // condition met.
+        if (access(path.c_str(), F_OK) != 0) {
+            if (errno == ENOENT) return WaitResult::Wait;
+        }
+        return WaitResult::Done;
+    };
+    return WaitForCondition(condition, timeout_ms);
+}
+
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms) {
+    auto condition = [&]() -> WaitResult {
+        if (access(path.c_str(), F_OK) == 0 || errno != ENOENT) {
+            return WaitResult::Wait;
+        }
+        return WaitResult::Done;
+    };
+    return WaitForCondition(condition, timeout_ms);
+}
+
+}  // namespace dm
+}  // namespace android
diff --git a/fs_mgr/libdm/utility.h b/fs_mgr/libdm/utility.h
new file mode 100644
index 0000000..58fa96b
--- /dev/null
+++ b/fs_mgr/libdm/utility.h
@@ -0,0 +1,31 @@
+// 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 <chrono>
+#include <functional>
+
+namespace android {
+namespace dm {
+
+enum class WaitResult { Wait, Done, Fail };
+
+bool WaitForFile(const std::string& path, const std::chrono::milliseconds& timeout_ms);
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms);
+bool WaitForCondition(const std::function<WaitResult()>& condition,
+                      const std::chrono::milliseconds& timeout_ms);
+
+}  // namespace dm
+}  // namespace android
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
new file mode 100644
index 0000000..fdc1583
--- /dev/null
+++ b/fs_mgr/libfiemap/Android.bp
@@ -0,0 +1,105 @@
+//
+// 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.
+//
+
+cc_library_headers {
+    name: "libfiemap_headers",
+    recovery_available: true,
+    export_include_dirs: ["include"],
+}
+
+filegroup {
+    name: "libfiemap_srcs",
+    srcs: [
+        "fiemap_writer.cpp",
+        "image_manager.cpp",
+        "metadata.cpp",
+        "split_fiemap_writer.cpp",
+        "utility.cpp",
+    ],
+}
+
+filegroup {
+    name: "libfiemap_binder_srcs",
+    srcs: [
+        "binder.cpp",
+    ],
+}
+
+cc_defaults {
+    name: "libfiemap_binder_defaults",
+    srcs: [":libfiemap_binder_srcs"],
+    whole_static_libs: [
+        "gsi_aidl_interface-cpp",
+        "libgsi",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+}
+
+// Open up a passthrough IImageManager interface. Use libfiemap_binder whenever
+// possible. This should only be used when binder is not available.
+filegroup {
+    name: "libfiemap_passthrough_srcs",
+    srcs: [
+        "passthrough.cpp",
+    ],
+}
+
+cc_test {
+    name: "fiemap_writer_test",
+    static_libs: [
+        "libbase",
+        "libdm",
+        "libfs_mgr",
+        "liblog",
+    ],
+
+    data: [
+        "testdata/unaligned_file",
+        "testdata/file_4k",
+        "testdata/file_32k",
+    ],
+
+    srcs: [
+        "fiemap_writer_test.cpp",
+    ],
+}
+
+cc_test {
+    name: "fiemap_image_test",
+    static_libs: [
+        "libdm",
+        "libext4_utils",
+        "libfs_mgr",
+        "liblp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+        "libcrypto_utils",
+        "libcutils",
+        "liblog",
+    ],
+    srcs: [
+        "image_test.cpp",
+    ],
+}
+
+vts_config {
+    name: "VtsFiemapWriterTest",
+}
diff --git a/fs_mgr/libfiemap_writer/AndroidTest.xml b/fs_mgr/libfiemap/AndroidTest.xml
similarity index 95%
rename from fs_mgr/libfiemap_writer/AndroidTest.xml
rename to fs_mgr/libfiemap/AndroidTest.xml
index 08cff0e..44c80fc 100644
--- a/fs_mgr/libfiemap_writer/AndroidTest.xml
+++ b/fs_mgr/libfiemap/AndroidTest.xml
@@ -24,6 +24,7 @@
         <option name="binary-test-source" value="_32bit::DATA/nativetest/fiemap_writer_test/fiemap_writer_test" />
         <option name="binary-test-source" value="_64bit::DATA/nativetest64/fiemap_writer_test/fiemap_writer_test" />
         <option name="binary-test-type" value="gtest"/>
+        <option name="precondition-first-api-level" value="29" />
         <option name="test-timeout" value="1m"/>
     </test>
 </configuration>
diff --git a/fs_mgr/libfiemap/README.md b/fs_mgr/libfiemap/README.md
new file mode 100644
index 0000000..62d610a
--- /dev/null
+++ b/fs_mgr/libfiemap/README.md
@@ -0,0 +1,75 @@
+libfiemap
+=============
+
+`libfiemap` is a library for creating block-devices that are backed by
+storage in read-write partitions. It exists primary for gsid. Generally, the
+library works by using `libfiemap_writer` to allocate large files within
+filesystem, and then tracks their extents.
+
+There are three main uses for `libfiemap`:
+ - Creating images that will act as block devices. For example, gsid needs to
+   create a `system_gsi` image to store Dynamic System Updates.
+ - Mapping the image as a block device while /data is mounted. This is fairly
+   tricky and is described in more detail below.
+ - Mapping the image as a block device during first-stage init. This is simple
+   because it uses the same logic from dynamic partitions.
+
+Image creation is done through `SplitFiemap`. Depending on the file system,
+a large image may have to be split into multiple files. On Ext4 the limit is
+16GiB and on FAT32 it's 4GiB. Images are saved into `/data/gsi/<name>/`
+where `<name>` is chosen by the process requesting the image.
+
+At the same time, a file called `/metadata/gsi/<name>/lp_metadata` is created.
+This is a super partition header that allows first-stage init to create dynamic
+partitions from the image files. It also tracks the canonical size of the image,
+since the file size may be larger due to alignment.
+
+Mapping
+-------
+
+It is easy to make block devices out of blocks on `/data` when it is not
+mounted, so first-stage init has no issues mapping dynamic partitions from
+images. After `/data` is mounted however, there are two problems:
+ - `/data` is encrypted.
+ - `/dev/block/by-name/data` may be marked as in-use.
+
+We break the problem down into three scenarios.
+
+### FDE and Metadata Encrypted Devices
+
+When FDE or metadata encryption is used, `/data` is not mounted from
+`/dev/block/by-name/data`. Instead, it is mounted from an intermediate
+`dm-crypt` or `dm-default-key` device. This means the underlying device is
+not marked in use, and we can create new dm-linear devices on top of it.
+
+On these devices, a block device for an image will consist of a single
+device-mapper device with a `dm-linear` table entry for each extent in the
+backing file.
+
+### Unencrypted and FBE-encrypted Devices
+
+When a device is unencrypted, or is encrypted with FBE but not metadata
+encryption, we instead use a loop device with `LOOP_SET_DIRECT_IO` enabled.
+Since `/data/gsi` has encryption disabled, this means the raw blocks will be
+unencrypted as well.
+
+### Split Images
+
+If an image was too large to store a single file on the underlying filesystem,
+on an FBE/unencrypted device we will have multiple loop devices. In this case,
+we create a device-mapper device as well. For each loop device it will have one
+`dm-linear` table entry spanning the length of the device.
+
+State Tracking
+--------------
+
+It's important that we know whether or not an image is currently in-use by a
+block device. It could be catastrophic to write to a dm-linear device if the
+underlying blocks are no longer owned by the original file. Thus, when mapping
+an image, we create a property called `gsid.mapped_image.<name>` and set it to
+the path of the block device.
+
+Additionally, we create a `/metadata/gsi/<subdir>/<name>.status` file. Each
+line in this file denotes a dependency on either a device-mapper node or a loop
+device. When deleting a block device, this file is used to release all
+resources.
diff --git a/fs_mgr/libfiemap/binder.cpp b/fs_mgr/libfiemap/binder.cpp
new file mode 100644
index 0000000..f99055a
--- /dev/null
+++ b/fs_mgr/libfiemap/binder.cpp
@@ -0,0 +1,258 @@
+//
+// 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.
+//
+
+#if !defined(__ANDROID_RECOVERY__)
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/gsi/IGsiService.h>
+#include <android/gsi/IGsid.h>
+#include <binder/IServiceManager.h>
+#include <libfiemap/image_manager.h>
+#include <libgsi/libgsi.h>
+
+namespace android {
+namespace fiemap {
+
+using namespace android::gsi;
+using namespace std::chrono_literals;
+
+class ImageManagerBinder final : public IImageManager {
+  public:
+    ImageManagerBinder(android::sp<IGsiService>&& service, android::sp<IImageService>&& manager);
+    bool CreateBackingImage(const std::string& name, uint64_t size, int flags) override;
+    bool DeleteBackingImage(const std::string& name) override;
+    bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
+                        std::string* path) override;
+    bool UnmapImageDevice(const std::string& name) override;
+    bool BackingImageExists(const std::string& name) override;
+    bool IsImageMapped(const std::string& name) override;
+    bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
+                                  std::string* dev) override;
+    bool ZeroFillNewImage(const std::string& name, uint64_t bytes) override;
+    bool RemoveAllImages() override;
+    bool DisableImage(const std::string& name) override;
+    bool RemoveDisabledImages() override;
+    bool GetMappedImageDevice(const std::string& name, std::string* device) override;
+    bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override;
+
+    std::vector<std::string> GetAllBackingImages() override;
+
+  private:
+    android::sp<IGsiService> service_;
+    android::sp<IImageService> manager_;
+};
+
+ImageManagerBinder::ImageManagerBinder(android::sp<IGsiService>&& service,
+                                       android::sp<IImageService>&& manager)
+    : service_(std::move(service)), manager_(std::move(manager)) {}
+
+bool ImageManagerBinder::CreateBackingImage(const std::string& name, uint64_t size, int flags) {
+    auto status = manager_->createBackingImage(name, size, flags);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return true;
+}
+
+bool ImageManagerBinder::DeleteBackingImage(const std::string& name) {
+    auto status = manager_->deleteBackingImage(name);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return true;
+}
+
+bool ImageManagerBinder::MapImageDevice(const std::string& name,
+                                        const std::chrono::milliseconds& timeout_ms,
+                                        std::string* path) {
+    int32_t timeout_ms_count =
+            static_cast<int32_t>(std::clamp<typename std::chrono::milliseconds::rep>(
+                    timeout_ms.count(), INT32_MIN, INT32_MAX));
+    MappedImage map;
+    auto status = manager_->mapImageDevice(name, timeout_ms_count, &map);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    *path = map.path;
+    return true;
+}
+
+bool ImageManagerBinder::UnmapImageDevice(const std::string& name) {
+    auto status = manager_->unmapImageDevice(name);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return true;
+}
+
+bool ImageManagerBinder::BackingImageExists(const std::string& name) {
+    bool retval;
+    auto status = manager_->backingImageExists(name, &retval);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return retval;
+}
+
+bool ImageManagerBinder::IsImageMapped(const std::string& name) {
+    bool retval;
+    auto status = manager_->isImageMapped(name, &retval);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return retval;
+}
+
+bool ImageManagerBinder::MapImageWithDeviceMapper(const IPartitionOpener& opener,
+                                                  const std::string& name, std::string* dev) {
+    (void)opener;
+    (void)name;
+    (void)dev;
+    LOG(ERROR) << "MapImageWithDeviceMapper is not available over binder.";
+    return false;
+}
+
+std::vector<std::string> ImageManagerBinder::GetAllBackingImages() {
+    std::vector<std::string> retval;
+    auto status = manager_->getAllBackingImages(&retval);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+    }
+    return retval;
+}
+
+bool ImageManagerBinder::ZeroFillNewImage(const std::string& name, uint64_t bytes) {
+    auto status = manager_->zeroFillNewImage(name, bytes);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return true;
+}
+
+bool ImageManagerBinder::RemoveAllImages() {
+    auto status = manager_->removeAllImages();
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return true;
+}
+
+bool ImageManagerBinder::DisableImage(const std::string&) {
+    LOG(ERROR) << __PRETTY_FUNCTION__ << " is not available over binder";
+    return false;
+}
+
+bool ImageManagerBinder::RemoveDisabledImages() {
+    auto status = manager_->removeDisabledImages();
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return true;
+}
+
+bool ImageManagerBinder::GetMappedImageDevice(const std::string& name, std::string* device) {
+    auto status = manager_->getMappedImageDevice(name, device);
+    if (!status.isOk()) {
+        LOG(ERROR) << __PRETTY_FUNCTION__
+                   << " binder returned: " << status.exceptionMessage().string();
+        return false;
+    }
+    return !device->empty();
+}
+
+bool ImageManagerBinder::MapAllImages(const std::function<bool(std::set<std::string>)>&) {
+    LOG(ERROR) << __PRETTY_FUNCTION__ << " not available over binder";
+    return false;
+}
+
+static android::sp<IGsid> AcquireIGsid(const std::chrono::milliseconds& timeout_ms) {
+    if (android::base::GetProperty("init.svc.gsid", "") != "running") {
+        if (!android::base::SetProperty("ctl.start", "gsid") ||
+            !android::base::WaitForProperty("init.svc.gsid", "running", timeout_ms)) {
+            LOG(ERROR) << "Could not start the gsid service";
+            return nullptr;
+        }
+        // Sleep for 250ms to give the service time to register.
+        usleep(250 * 1000);
+    }
+    auto sm = android::defaultServiceManager();
+    auto name = android::String16(kGsiServiceName);
+    auto service = sm->checkService(name);
+    return android::interface_cast<IGsid>(service);
+}
+
+static android::sp<IGsid> GetGsiService(const std::chrono::milliseconds& timeout_ms) {
+    auto start_time = std::chrono::steady_clock::now();
+
+    std::chrono::milliseconds elapsed = std::chrono::milliseconds::zero();
+    do {
+        if (auto gsid = AcquireIGsid(timeout_ms - elapsed); gsid != nullptr) {
+            return gsid;
+        }
+        auto now = std::chrono::steady_clock::now();
+        elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+    } while (elapsed <= timeout_ms);
+
+    LOG(ERROR) << "Timed out trying to acquire IGsid interface";
+    return nullptr;
+}
+
+std::unique_ptr<IImageManager> IImageManager::Open(const std::string& dir,
+                                                   const std::chrono::milliseconds& timeout_ms) {
+    auto gsid = GetGsiService(timeout_ms);
+    if (!gsid) {
+        return nullptr;
+    }
+
+    android::sp<IGsiService> service;
+    auto status = gsid->getClient(&service);
+    if (!status.isOk() || !service) {
+        LOG(ERROR) << "Could not acquire IGsiService";
+        return nullptr;
+    }
+
+    android::sp<IImageService> manager;
+    status = service->openImageService(dir, &manager);
+    if (!status.isOk() || !manager) {
+        LOG(ERROR) << "Could not acquire IImageManager: " << status.exceptionMessage().string();
+        return nullptr;
+    }
+    return std::make_unique<ImageManagerBinder>(std::move(service), std::move(manager));
+}
+
+}  // namespace fiemap
+}  // namespace android
+
+#endif  // __ANDROID_RECOVERY__
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap/fiemap_writer.cpp
similarity index 71%
rename from fs_mgr/libfiemap_writer/fiemap_writer.cpp
rename to fs_mgr/libfiemap/fiemap_writer.cpp
index e3803d5..d34e0b8 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <libfiemap_writer/fiemap_writer.h>
+#include <libfiemap/fiemap_writer.h>
 
 #include <dirent.h>
 #include <fcntl.h>
@@ -37,13 +37,16 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <libdm/dm.h>
+#include "utility.h"
 
 namespace android {
-namespace fiemap_writer {
+namespace fiemap {
 
-// We are expecting no more than 512 extents in a fiemap of the file we create.
-// If we find more, then it is treated as error for now.
-static constexpr const uint32_t kMaxExtents = 512;
+using namespace android::dm;
+
+// We cap the maximum number of extents as a sanity measure.
+static constexpr uint32_t kMaxExtents = 50000;
 
 // TODO: Fallback to using fibmap if FIEMAP_EXTENT_MERGED is set.
 static constexpr const uint32_t kUnsupportedExtentFlags =
@@ -60,41 +63,75 @@
     }
 }
 
-static bool BlockDeviceToName(uint32_t major, uint32_t minor, std::string* bdev_name) {
-    // The symlinks in /sys/dev/block point to the block device node under /sys/device/..
-    // The directory name in the target corresponds to the name of the block device. We use
-    // that to extract the block device name.
-    // e.g for block device name 'ram0', there exists a symlink named '1:0' in /sys/dev/block as
-    // follows.
-    //    1:0 -> ../../devices/virtual/block/ram0
-    std::string sysfs_path = ::android::base::StringPrintf("/sys/dev/block/%u:%u", major, minor);
-    std::string sysfs_bdev;
-
-    if (!::android::base::Readlink(sysfs_path, &sysfs_bdev)) {
-        PLOG(ERROR) << "Failed to read link at: " << sysfs_path;
+static bool ValidateDmTarget(const DeviceMapper::TargetInfo& target) {
+    const auto& entry = target.spec;
+    if (entry.sector_start != 0) {
+        LOG(INFO) << "Stopping at target with non-zero starting sector";
         return false;
     }
 
-    *bdev_name = ::android::base::Basename(sysfs_bdev);
-    // Paranoid sanity check to make sure we just didn't get the
-    // input in return as-is.
-    if (sysfs_bdev == *bdev_name) {
-        LOG(ERROR) << "Malformed symlink for block device: " << sysfs_bdev;
-        return false;
+    auto target_type = DeviceMapper::GetTargetType(entry);
+    if (target_type == "bow" || target_type == "default-key" || target_type == "crypt") {
+        return true;
     }
-
-    return true;
-}
-
-static bool DeviceMapperStackPop(const std::string& bdev, std::string* bdev_raw) {
-    // TODO: Stop popping the device mapper stack if dm-linear target is found
-    if (!::android::base::StartsWith(bdev, "dm-")) {
-        // We are at the bottom of the device mapper stack.
-        *bdev_raw = bdev;
+    if (target_type == "linear") {
+        auto pieces = android::base::Split(target.data, " ");
+        if (pieces[1] != "0") {
+            LOG(INFO) << "Stopping at complex linear target with non-zero starting sector: "
+                      << pieces[1];
+            return false;
+        }
         return true;
     }
 
-    std::string dm_leaf_dir = ::android::base::StringPrintf("/sys/block/%s/slaves", bdev.c_str());
+    LOG(INFO) << "Stopping at complex target type " << target_type;
+    return false;
+}
+
+static bool DeviceMapperStackPop(const std::string& bdev, std::string* bdev_raw) {
+    *bdev_raw = bdev;
+
+    if (!::android::base::StartsWith(bdev, "dm-")) {
+        // We are at the bottom of the device mapper stack.
+        return true;
+    }
+
+    // Get the device name.
+    auto dm_name_file = "/sys/block/" + bdev + "/dm/name";
+    std::string dm_name;
+    if (!android::base::ReadFileToString(dm_name_file, &dm_name)) {
+        PLOG(ERROR) << "Could not read file: " << dm_name_file;
+        return false;
+    }
+    dm_name = android::base::Trim(dm_name);
+
+    auto& dm = DeviceMapper::Instance();
+    std::vector<DeviceMapper::TargetInfo> table;
+    if (!dm.GetTableInfo(dm_name, &table)) {
+        LOG(ERROR) << "Could not read device-mapper table for " << dm_name << " at " << bdev;
+        return false;
+    }
+
+    // The purpose of libfiemap is to provide an extent-based view into
+    // a file. This is difficult if devices are not layered in a 1:1 manner;
+    // we would have to translate and break up extents based on the actual
+    // block mapping. Since this is too complex, we simply stop processing
+    // the device-mapper stack if we encounter a complex case.
+    //
+    // It is up to the caller to decide whether stopping at a virtual block
+    // device is allowable. In most cases it is not, because we want either
+    // "userdata" or an external volume. It is useful for tests however.
+    // Callers can check by comparing the device number to that of userdata,
+    // or by checking whether is a device-mapper node.
+    if (table.size() > 1) {
+        LOG(INFO) << "Stopping at complex table for " << dm_name << " at " << bdev;
+        return true;
+    }
+    if (!ValidateDmTarget(table[0])) {
+        return true;
+    }
+
+    auto dm_leaf_dir = "/sys/block/" + bdev + "/slaves";
     auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dm_leaf_dir.c_str()), closedir);
     if (d == nullptr) {
         PLOG(ERROR) << "Failed to open: " << dm_leaf_dir;
@@ -196,8 +233,7 @@
     return sb.st_size;
 }
 
-static bool PerformFileChecks(const std::string& file_path, uint64_t file_size, uint64_t* blocksz,
-                              uint32_t* fs_type) {
+static bool PerformFileChecks(const std::string& file_path, uint64_t* blocksz, uint32_t* fs_type) {
     struct statfs64 sfs;
     if (statfs64(file_path.c_str(), &sfs)) {
         PLOG(ERROR) << "Failed to read file system status at: " << file_path;
@@ -221,12 +257,6 @@
             return false;
     }
 
-    uint64_t available_bytes = sfs.f_bsize * sfs.f_bavail;
-    if (available_bytes <= file_size) {
-        LOG(ERROR) << "Not enough free space in file system to create file of size : " << file_size;
-        return false;
-    }
-
     *blocksz = sfs.f_bsize;
     *fs_type = sfs.f_type;
     return true;
@@ -268,34 +298,93 @@
     return true;
 }
 
-static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
-                         uint64_t file_size, unsigned int fs_type,
-                         std::function<bool(uint64_t, uint64_t)> on_progress) {
-    // Reserve space for the file on the file system and write it out to make sure the extents
-    // don't come back unwritten. Return from this function with the kernel file offset set to 0.
-    // If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
-    // aren't moved around.
-    switch (fs_type) {
-        case EXT4_SUPER_MAGIC:
-        case F2FS_SUPER_MAGIC:
-            if (fallocate(file_fd, FALLOC_FL_ZERO_RANGE, 0, file_size)) {
-                PLOG(ERROR) << "Failed to allocate space for file: " << file_path
-                            << " size: " << file_size;
-                return false;
-            }
-            break;
-        case MSDOS_SUPER_MAGIC:
-            // fallocate() is not supported, and not needed, since VFAT does not support holes.
-            // Instead we can perform a much faster allocation.
-            return FallocateFallback(file_fd, blocksz, file_size, file_path, on_progress);
-        default:
-            LOG(ERROR) << "Missing fallocate() support for file system " << fs_type;
-            return false;
+// F2FS-specific ioctl
+// It requires the below kernel commit merged in v4.16-rc1.
+//   1ad71a27124c ("f2fs: add an ioctl to disable GC for specific file")
+// In android-4.4,
+//   56ee1e817908 ("f2fs: updates on v4.16-rc1")
+// In android-4.9,
+//   2f17e34672a8 ("f2fs: updates on v4.16-rc1")
+// In android-4.14,
+//   ce767d9a55bc ("f2fs: updates on v4.16-rc1")
+#ifndef F2FS_IOC_SET_PIN_FILE
+#ifndef F2FS_IOCTL_MAGIC
+#define F2FS_IOCTL_MAGIC 0xf5
+#endif
+#define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, __u32)
+#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
+#endif
+
+static bool IsFilePinned(int file_fd, const std::string& file_path, uint32_t fs_type) {
+    if (fs_type != F2FS_SUPER_MAGIC) {
+        // No pinning necessary for ext4 or vfat. The blocks, once allocated,
+        // are expected to be fixed.
+        return true;
     }
 
-    // write zeroes in 'blocksz' byte increments until we reach file_size to make sure the data
-    // blocks are actually written to by the file system and thus getting rid of the holes in the
-    // file.
+    // f2fs: export FS_NOCOW_FL flag to user
+    uint32_t flags;
+    int error = ioctl(file_fd, FS_IOC_GETFLAGS, &flags);
+    if (error < 0) {
+        if ((errno == ENOTTY) || (errno == ENOTSUP)) {
+            PLOG(ERROR) << "Failed to get flags, not supported by kernel: " << file_path;
+        } else {
+            PLOG(ERROR) << "Failed to get flags: " << file_path;
+        }
+        return false;
+    }
+    if (!(flags & FS_NOCOW_FL)) {
+        return false;
+    }
+
+    // F2FS_IOC_GET_PIN_FILE returns the number of blocks moved.
+    uint32_t moved_blocks_nr;
+    error = ioctl(file_fd, F2FS_IOC_GET_PIN_FILE, &moved_blocks_nr);
+    if (error < 0) {
+        if ((errno == ENOTTY) || (errno == ENOTSUP)) {
+            PLOG(ERROR) << "Failed to get file pin status, not supported by kernel: " << file_path;
+        } else {
+            PLOG(ERROR) << "Failed to get file pin status: " << file_path;
+        }
+        return false;
+    }
+
+    if (moved_blocks_nr) {
+        LOG(WARNING) << moved_blocks_nr << " blocks moved in file " << file_path;
+    }
+    return moved_blocks_nr == 0;
+}
+
+static bool PinFile(int file_fd, const std::string& file_path, uint32_t fs_type) {
+    if (IsFilePinned(file_fd, file_path, fs_type)) {
+        return true;
+    }
+    if (fs_type != F2FS_SUPER_MAGIC) {
+        // No pinning necessary for ext4/msdos. The blocks, once allocated, are
+        // expected to be fixed.
+        return true;
+    }
+
+    uint32_t pin_status = 1;
+    int error = ioctl(file_fd, F2FS_IOC_SET_PIN_FILE, &pin_status);
+    if (error < 0) {
+        if ((errno == ENOTTY) || (errno == ENOTSUP)) {
+            PLOG(ERROR) << "Failed to pin file, not supported by kernel: " << file_path;
+        } else {
+            PLOG(ERROR) << "Failed to pin file: " << file_path;
+        }
+        return false;
+    }
+
+    return true;
+}
+
+// write zeroes in 'blocksz' byte increments until we reach file_size to make sure the data
+// blocks are actually written to by the file system and thus getting rid of the holes in the
+// file.
+static bool WriteZeroes(int file_fd, const std::string& file_path, size_t blocksz,
+                        uint64_t file_size,
+                        const std::function<bool(uint64_t, uint64_t)>& on_progress) {
     auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, blocksz), free);
     if (buffer == nullptr) {
         LOG(ERROR) << "failed to allocate memory for writing file";
@@ -333,6 +422,50 @@
         PLOG(ERROR) << "Failed to reset offset at the beginning of : " << file_path;
         return false;
     }
+    return true;
+}
+
+// Reserve space for the file on the file system and write it out to make sure the extents
+// don't come back unwritten. Return from this function with the kernel file offset set to 0.
+// If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
+// aren't moved around.
+static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
+                         uint64_t file_size, unsigned int fs_type,
+                         std::function<bool(uint64_t, uint64_t)> on_progress) {
+    bool need_explicit_writes = true;
+    switch (fs_type) {
+        case EXT4_SUPER_MAGIC:
+            break;
+        case F2FS_SUPER_MAGIC: {
+            bool supported;
+            if (!F2fsPinBeforeAllocate(file_fd, &supported)) {
+                return false;
+            }
+            if (supported) {
+                if (!PinFile(file_fd, file_path, fs_type)) {
+                    return false;
+                }
+                need_explicit_writes = false;
+            }
+            break;
+        }
+        case MSDOS_SUPER_MAGIC:
+            // fallocate() is not supported, and not needed, since VFAT does not support holes.
+            // Instead we can perform a much faster allocation.
+            return FallocateFallback(file_fd, blocksz, file_size, file_path, on_progress);
+        default:
+            LOG(ERROR) << "Missing fallocate() support for file system " << fs_type;
+            return false;
+    }
+
+    if (fallocate(file_fd, 0, 0, file_size)) {
+        PLOG(ERROR) << "Failed to allocate space for file: " << file_path << " size: " << file_size;
+        return false;
+    }
+
+    if (need_explicit_writes && !WriteZeroes(file_fd, file_path, blocksz, file_size, on_progress)) {
+        return false;
+    }
 
     // flush all writes here ..
     if (fsync(file_fd)) {
@@ -347,100 +480,6 @@
     return true;
 }
 
-static bool PinFile(int file_fd, const std::string& file_path, uint32_t fs_type) {
-    if (fs_type != F2FS_SUPER_MAGIC) {
-        // No pinning necessary for ext4/msdos. The blocks, once allocated, are
-        // expected to be fixed.
-        return true;
-    }
-
-// F2FS-specific ioctl
-// It requires the below kernel commit merged in v4.16-rc1.
-//   1ad71a27124c ("f2fs: add an ioctl to disable GC for specific file")
-// In android-4.4,
-//   56ee1e817908 ("f2fs: updates on v4.16-rc1")
-// In android-4.9,
-//   2f17e34672a8 ("f2fs: updates on v4.16-rc1")
-// In android-4.14,
-//   ce767d9a55bc ("f2fs: updates on v4.16-rc1")
-#ifndef F2FS_IOC_SET_PIN_FILE
-#ifndef F2FS_IOCTL_MAGIC
-#define F2FS_IOCTL_MAGIC 0xf5
-#endif
-#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
-#endif
-
-    uint32_t pin_status = 1;
-    int error = ioctl(file_fd, F2FS_IOC_SET_PIN_FILE, &pin_status);
-    if (error < 0) {
-        if ((errno == ENOTTY) || (errno == ENOTSUP)) {
-            PLOG(ERROR) << "Failed to pin file, not supported by kernel: " << file_path;
-        } else {
-            PLOG(ERROR) << "Failed to pin file: " << file_path;
-        }
-        return false;
-    }
-
-    return true;
-}
-
-static bool IsFilePinned(int file_fd, const std::string& file_path, uint32_t fs_type) {
-    if (fs_type != F2FS_SUPER_MAGIC) {
-        // No pinning necessary for ext4 or vfat. The blocks, once allocated,
-        // are expected to be fixed.
-        return true;
-    }
-
-// F2FS-specific ioctl
-// It requires the below kernel commit merged in v4.16-rc1.
-//   1ad71a27124c ("f2fs: add an ioctl to disable GC for specific file")
-// In android-4.4,
-//   56ee1e817908 ("f2fs: updates on v4.16-rc1")
-// In android-4.9,
-//   2f17e34672a8 ("f2fs: updates on v4.16-rc1")
-// In android-4.14,
-//   ce767d9a55bc ("f2fs: updates on v4.16-rc1")
-#ifndef F2FS_IOC_GET_PIN_FILE
-#ifndef F2FS_IOCTL_MAGIC
-#define F2FS_IOCTL_MAGIC 0xf5
-#endif
-#define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, __u32)
-#endif
-
-    // f2fs: export FS_NOCOW_FL flag to user
-    uint32_t flags;
-    int error = ioctl(file_fd, FS_IOC_GETFLAGS, &flags);
-    if (error < 0) {
-        if ((errno == ENOTTY) || (errno == ENOTSUP)) {
-            PLOG(ERROR) << "Failed to get flags, not supported by kernel: " << file_path;
-        } else {
-            PLOG(ERROR) << "Failed to get flags: " << file_path;
-        }
-        return false;
-    }
-    if (!(flags & FS_NOCOW_FL)) {
-        LOG(ERROR) << "It is not pinned: " << file_path;
-        return false;
-    }
-
-    // F2FS_IOC_GET_PIN_FILE returns the number of blocks moved.
-    uint32_t moved_blocks_nr;
-    error = ioctl(file_fd, F2FS_IOC_GET_PIN_FILE, &moved_blocks_nr);
-    if (error < 0) {
-        if ((errno == ENOTTY) || (errno == ENOTSUP)) {
-            PLOG(ERROR) << "Failed to get file pin status, not supported by kernel: " << file_path;
-        } else {
-            PLOG(ERROR) << "Failed to get file pin status: " << file_path;
-        }
-        return false;
-    }
-
-    if (moved_blocks_nr) {
-        LOG(ERROR) << moved_blocks_nr << " blocks moved in file " << file_path;
-    }
-    return moved_blocks_nr == 0;
-}
-
 bool FiemapWriter::HasPinnedExtents(const std::string& file_path) {
     android::base::unique_fd fd(open(file_path.c_str(), O_NOFOLLOW | O_CLOEXEC | O_RDONLY));
     if (fd < 0) {
@@ -456,10 +495,102 @@
     return IsFilePinned(fd, file_path, sfs.f_type);
 }
 
+static bool CountFiemapExtents(int file_fd, const std::string& file_path, uint32_t* num_extents) {
+    struct fiemap fiemap = {};
+    fiemap.fm_start = 0;
+    fiemap.fm_length = UINT64_MAX;
+    fiemap.fm_flags = FIEMAP_FLAG_SYNC;
+    fiemap.fm_extent_count = 0;
+
+    if (ioctl(file_fd, FS_IOC_FIEMAP, &fiemap)) {
+        PLOG(ERROR) << "Failed to get FIEMAP from the kernel for file: " << file_path;
+        return false;
+    }
+
+    if (num_extents) {
+        *num_extents = fiemap.fm_mapped_extents;
+    }
+    return true;
+}
+
+static bool IsValidExtent(const fiemap_extent* extent, std::string_view file_path) {
+    if (extent->fe_flags & kUnsupportedExtentFlags) {
+        LOG(ERROR) << "Extent at location " << extent->fe_logical << " of file " << file_path
+                   << " has unsupported flags";
+        return false;
+    }
+    return true;
+}
+
+static bool IsLastExtent(const fiemap_extent* extent) {
+    if (!(extent->fe_flags & FIEMAP_EXTENT_LAST)) {
+        LOG(ERROR) << "Extents are being received out-of-order";
+        return false;
+    }
+    return true;
+}
+
+static bool FiemapToExtents(struct fiemap* fiemap, std::vector<struct fiemap_extent>* extents,
+                            uint32_t num_extents, std::string_view file_path) {
+    if (num_extents == 0) return false;
+
+    const struct fiemap_extent* last_extent = &fiemap->fm_extents[num_extents - 1];
+    if (!IsLastExtent(last_extent)) {
+        LOG(ERROR) << "FIEMAP did not return a final extent for file: " << file_path;
+        return false;
+    }
+
+    // Iterate through each extent, read and make sure its valid before adding it to the vector
+    // merging contiguous extents.
+    fiemap_extent* prev = &fiemap->fm_extents[0];
+    if (!IsValidExtent(prev, file_path)) return false;
+
+    for (uint32_t i = 1; i < num_extents; i++) {
+        fiemap_extent* next = &fiemap->fm_extents[i];
+
+        // Make sure extents are returned in order
+        if (next != last_extent && IsLastExtent(next)) return false;
+
+        // Check if extent's flags are valid
+        if (!IsValidExtent(next, file_path)) return false;
+
+        // Check if the current extent is contiguous with the previous one.
+        // An extent can be combined with its predecessor only if:
+        //  1. There is no physical space between the previous and the current
+        //  extent, and
+        //  2. The physical distance between the previous and current extent
+        //  corresponds to their logical distance (contiguous mapping).
+        if (prev->fe_physical + prev->fe_length == next->fe_physical &&
+            next->fe_physical - prev->fe_physical == next->fe_logical - prev->fe_logical) {
+            prev->fe_length += next->fe_length;
+        } else {
+            extents->emplace_back(*prev);
+            prev = next;
+        }
+    }
+    extents->emplace_back(*prev);
+
+    return true;
+}
+
 static bool ReadFiemap(int file_fd, const std::string& file_path,
                        std::vector<struct fiemap_extent>* extents) {
+    uint32_t num_extents;
+    if (!CountFiemapExtents(file_fd, file_path, &num_extents)) {
+        return false;
+    }
+    if (num_extents == 0) {
+        LOG(ERROR) << "File " << file_path << " has zero extents";
+        return false;
+    }
+    if (num_extents > kMaxExtents) {
+        LOG(ERROR) << "File has " << num_extents << ", maximum is " << kMaxExtents << ": "
+                   << file_path;
+        return false;
+    }
+
     uint64_t fiemap_size =
-            sizeof(struct fiemap_extent) + kMaxExtents * sizeof(struct fiemap_extent);
+            sizeof(struct fiemap_extent) + num_extents * sizeof(struct fiemap_extent);
     auto buffer = std::unique_ptr<void, decltype(&free)>(calloc(1, fiemap_size), free);
     if (buffer == nullptr) {
         LOG(ERROR) << "Failed to allocate memory for fiemap";
@@ -471,48 +602,19 @@
     fiemap->fm_length = UINT64_MAX;
     // make sure file is synced to disk before we read the fiemap
     fiemap->fm_flags = FIEMAP_FLAG_SYNC;
-    fiemap->fm_extent_count = kMaxExtents;
+    fiemap->fm_extent_count = num_extents;
 
     if (ioctl(file_fd, FS_IOC_FIEMAP, fiemap)) {
         PLOG(ERROR) << "Failed to get FIEMAP from the kernel for file: " << file_path;
         return false;
     }
-
-    if (fiemap->fm_mapped_extents == 0) {
-        LOG(ERROR) << "File " << file_path << " has zero extents";
+    if (fiemap->fm_mapped_extents != num_extents) {
+        LOG(ERROR) << "FIEMAP returned unexpected extent count (" << num_extents
+                   << " expected, got " << fiemap->fm_mapped_extents << ") for file: " << file_path;
         return false;
     }
 
-    // Iterate through each extent read and make sure its valid before adding it to the vector
-    bool last_extent_seen = false;
-    struct fiemap_extent* extent = &fiemap->fm_extents[0];
-    for (uint32_t i = 0; i < fiemap->fm_mapped_extents; i++, extent++) {
-        // LogExtent(i + 1, *extent);
-        if (extent->fe_flags & kUnsupportedExtentFlags) {
-            LOG(ERROR) << "Extent " << i + 1 << " of file " << file_path
-                       << " has unsupported flags";
-            extents->clear();
-            return false;
-        }
-
-        if (extent->fe_flags & FIEMAP_EXTENT_LAST) {
-            last_extent_seen = true;
-            if (i != (fiemap->fm_mapped_extents - 1)) {
-                LOG(WARNING) << "Extents are being received out-of-order";
-            }
-        }
-        extents->emplace_back(std::move(*extent));
-    }
-
-    if (!last_extent_seen) {
-        // The file is possibly too fragmented.
-        if (fiemap->fm_mapped_extents == kMaxExtents) {
-            LOG(ERROR) << "File is too fragmented, needs more than " << kMaxExtents << " extents.";
-        }
-        extents->clear();
-    }
-
-    return last_extent_seen;
+    return FiemapToExtents(fiemap, extents, num_extents, file_path);
 }
 
 static bool ReadFibmap(int file_fd, const std::string& file_path,
@@ -557,6 +659,10 @@
                                              .fe_physical = static_cast<uint64_t>(block) * blksize,
                                              .fe_length = static_cast<uint64_t>(blksize),
                                              .fe_flags = 0});
+            if (extents->size() > kMaxExtents) {
+                LOG(ERROR) << "File has more than " << kMaxExtents << "extents: " << file_path;
+                return false;
+            }
         }
         last_block = block;
     }
@@ -619,7 +725,7 @@
 
     uint64_t blocksz;
     uint32_t fs_type;
-    if (!PerformFileChecks(abs_path, file_size, &blocksz, &fs_type)) {
+    if (!PerformFileChecks(abs_path, &blocksz, &fs_type)) {
         LOG(ERROR) << "Failed to validate file or file system for file:" << abs_path;
         cleanup(abs_path, create);
         return nullptr;
@@ -678,5 +784,5 @@
     return fmap;
 }
 
-}  // namespace fiemap_writer
+}  // namespace fiemap
 }  // namespace android
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp b/fs_mgr/libfiemap/fiemap_writer_test.cpp
similarity index 97%
rename from fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
rename to fs_mgr/libfiemap/fiemap_writer_test.cpp
index dda7dfd..4ac7161 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer_test.cpp
@@ -33,17 +33,17 @@
 #include <android-base/unique_fd.h>
 #include <gtest/gtest.h>
 #include <libdm/loop_control.h>
-#include <libfiemap_writer/fiemap_writer.h>
-#include <libfiemap_writer/split_fiemap_writer.h>
+#include <libfiemap/fiemap_writer.h>
+#include <libfiemap/split_fiemap_writer.h>
 
 #include "utility.h"
 
 namespace android {
-namespace fiemap_writer {
+namespace fiemap {
 
 using namespace std;
 using namespace std::string_literals;
-using namespace android::fiemap_writer;
+using namespace android::fiemap;
 using unique_fd = android::base::unique_fd;
 using LoopDevice = android::dm::LoopDevice;
 
@@ -414,7 +414,7 @@
         int ret = system(dd_cmd.c_str());
         ASSERT_EQ(ret, 0);
         // Get and attach a loop device to the filesystem we created
-        LoopDevice loop_dev(fs_path);
+        LoopDevice loop_dev(fs_path, 10s);
         ASSERT_TRUE(loop_dev.valid());
         // create file system
         ret = system(mkfs_cmd.c_str());
@@ -456,7 +456,7 @@
         int ret = system(dd_cmd.c_str());
         ASSERT_EQ(ret, 0);
         // Get and attach a loop device to the filesystem we created
-        LoopDevice loop_dev(fs_path);
+        LoopDevice loop_dev(fs_path, 10s);
         ASSERT_TRUE(loop_dev.valid());
         // create file system
         ret = system(mkfs_cmd.c_str());
@@ -491,10 +491,10 @@
     return true;
 }
 
-}  // namespace fiemap_writer
+}  // namespace fiemap
 }  // namespace android
 
-using namespace android::fiemap_writer;
+using namespace android::fiemap;
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
diff --git a/fs_mgr/libfiemap/image_manager.cpp b/fs_mgr/libfiemap/image_manager.cpp
new file mode 100644
index 0000000..baa5de4
--- /dev/null
+++ b/fs_mgr/libfiemap/image_manager.cpp
@@ -0,0 +1,737 @@
+//
+// 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 <libfiemap/image_manager.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr/file_wait.h>
+#include <fs_mgr_dm_linear.h>
+#include <libdm/loop_control.h>
+#include <libfiemap/split_fiemap_writer.h>
+
+#include "metadata.h"
+#include "utility.h"
+
+namespace android {
+namespace fiemap {
+
+using namespace std::literals;
+using android::base::unique_fd;
+using android::dm::DeviceMapper;
+using android::dm::DmDeviceState;
+using android::dm::DmTable;
+using android::dm::DmTargetLinear;
+using android::dm::LoopControl;
+using android::fs_mgr::CreateLogicalPartition;
+using android::fs_mgr::CreateLogicalPartitionParams;
+using android::fs_mgr::CreateLogicalPartitions;
+using android::fs_mgr::DestroyLogicalPartition;
+using android::fs_mgr::GetBlockDevicePartitionName;
+using android::fs_mgr::GetBlockDevicePartitionNames;
+using android::fs_mgr::GetPartitionName;
+
+static constexpr char kTestImageMetadataDir[] = "/metadata/gsi/test";
+
+std::unique_ptr<ImageManager> ImageManager::Open(const std::string& dir_prefix) {
+    auto metadata_dir = "/metadata/gsi/" + dir_prefix;
+    auto data_dir = "/data/gsi/" + dir_prefix;
+    return Open(metadata_dir, data_dir);
+}
+
+std::unique_ptr<ImageManager> ImageManager::Open(const std::string& metadata_dir,
+                                                 const std::string& data_dir) {
+    return std::unique_ptr<ImageManager>(new ImageManager(metadata_dir, data_dir));
+}
+
+ImageManager::ImageManager(const std::string& metadata_dir, const std::string& data_dir)
+    : metadata_dir_(metadata_dir), data_dir_(data_dir) {
+    partition_opener_ = std::make_unique<android::fs_mgr::PartitionOpener>();
+}
+
+std::string ImageManager::GetImageHeaderPath(const std::string& name) {
+    return JoinPaths(data_dir_, name) + ".img";
+}
+
+// The status file has one entry per line, with each entry formatted as one of:
+//   dm:<name>
+//   loop:<path>
+//
+// This simplifies the process of tearing down a mapping, since we can simply
+// unmap each entry in the order it appears.
+std::string ImageManager::GetStatusFilePath(const std::string& image_name) {
+    return JoinPaths(metadata_dir_, image_name) + ".status";
+}
+
+static std::string GetStatusPropertyName(const std::string& image_name) {
+    // Note: we don't prefix |image_name|, because CreateLogicalPartition won't
+    // prefix the name either. There are no plans to change this at the moment,
+    // consumers of the image API must take care to use globally-unique image
+    // names.
+    return "gsid.mapped_image." + image_name;
+}
+
+void ImageManager::set_partition_opener(std::unique_ptr<IPartitionOpener>&& opener) {
+    partition_opener_ = std::move(opener);
+}
+
+bool ImageManager::IsImageMapped(const std::string& image_name) {
+    auto prop_name = GetStatusPropertyName(image_name);
+    if (android::base::GetProperty(prop_name, "").empty()) {
+        // If mapped in first-stage init, the dm-device will exist but not the
+        // property.
+        auto& dm = DeviceMapper::Instance();
+        return dm.GetState(image_name) != DmDeviceState::INVALID;
+    }
+    return true;
+}
+
+std::vector<std::string> ImageManager::GetAllBackingImages() {
+    std::vector<std::string> images;
+    if (!MetadataExists(metadata_dir_)) {
+        return images;
+    }
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (metadata) {
+        for (auto&& partition : metadata->partitions) {
+            images.push_back(partition.name);
+        }
+    }
+    return images;
+}
+
+bool ImageManager::PartitionExists(const std::string& name) {
+    if (!MetadataExists(metadata_dir_)) {
+        return false;
+    }
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return false;
+    }
+    return !!FindPartition(*metadata.get(), name);
+}
+
+bool ImageManager::BackingImageExists(const std::string& name) {
+    auto header_file = GetImageHeaderPath(name);
+    return access(header_file.c_str(), F_OK) == 0;
+}
+
+bool ImageManager::CreateBackingImage(const std::string& name, uint64_t size, int flags) {
+    return CreateBackingImage(name, size, flags, nullptr);
+}
+
+static bool IsUnreliablePinningAllowed(const std::string& path) {
+    return android::base::StartsWith(path, "/data/gsi/dsu/") ||
+           android::base::StartsWith(path, "/data/gsi/test/") ||
+           android::base::StartsWith(path, "/data/gsi/ota/test/");
+}
+
+bool ImageManager::CreateBackingImage(const std::string& name, uint64_t size, int flags,
+                                      std::function<bool(uint64_t, uint64_t)>&& on_progress) {
+    auto data_path = GetImageHeaderPath(name);
+    auto fw = SplitFiemap::Create(data_path, size, 0, on_progress);
+    if (!fw) {
+        return false;
+    }
+
+    bool reliable_pinning;
+    if (!FilesystemHasReliablePinning(data_path, &reliable_pinning)) {
+        return false;
+    }
+    if (!reliable_pinning && !IsUnreliablePinningAllowed(data_path)) {
+        // For historical reasons, we allow unreliable pinning for certain use
+        // cases (DSUs, testing) because the ultimate use case is either
+        // developer-oriented or ephemeral (the intent is to boot immediately
+        // into DSUs). For everything else - such as snapshots/OTAs or adb
+        // remount, we have a higher bar, and require the filesystem to support
+        // proper pinning.
+        LOG(ERROR) << "File system does not have reliable block pinning";
+        SplitFiemap::RemoveSplitFiles(data_path);
+        return false;
+    }
+
+    // Except for testing, we do not allow persisting metadata that references
+    // device-mapper devices. It just doesn't make sense, because the device
+    // numbering may change on reboot. We allow it for testing since the images
+    // are not meant to survive reboot. Outside of tests, this can only happen
+    // if device-mapper is stacked in some complex way not supported by
+    // FiemapWriter.
+    auto device_path = GetDevicePathForFile(fw.get());
+    if (android::base::StartsWith(device_path, "/dev/block/dm-") &&
+        !android::base::StartsWith(metadata_dir_, kTestImageMetadataDir)) {
+        LOG(ERROR) << "Cannot persist images against device-mapper device: " << device_path;
+
+        fw = {};
+        SplitFiemap::RemoveSplitFiles(data_path);
+        return false;
+    }
+
+    bool readonly = !!(flags & CREATE_IMAGE_READONLY);
+    if (!UpdateMetadata(metadata_dir_, name, fw.get(), size, readonly)) {
+        return false;
+    }
+
+    if (flags & CREATE_IMAGE_ZERO_FILL) {
+        if (!ZeroFillNewImage(name, 0)) {
+            DeleteBackingImage(name);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ImageManager::ZeroFillNewImage(const std::string& name, uint64_t bytes) {
+    auto data_path = GetImageHeaderPath(name);
+
+    // See the comment in MapImageDevice() about how this works.
+    std::string block_device;
+    bool can_use_devicemapper;
+    if (!FiemapWriter::GetBlockDeviceForFile(data_path, &block_device, &can_use_devicemapper)) {
+        LOG(ERROR) << "Could not determine block device for " << data_path;
+        return false;
+    }
+
+    if (!can_use_devicemapper) {
+        // We've backed with loop devices, and since we store files in an
+        // unencrypted folder, the initial zeroes we wrote will suffice.
+        return true;
+    }
+
+    // data is dm-crypt, or FBE + dm-default-key. This means the zeroes written
+    // by libfiemap were encrypted, so we need to map the image in and correct
+    // this.
+    auto device = MappedDevice::Open(this, 10s, name);
+    if (!device) {
+        return false;
+    }
+
+    static constexpr size_t kChunkSize = 4096;
+    std::string zeroes(kChunkSize, '\0');
+
+    uint64_t remaining;
+    if (bytes) {
+        remaining = bytes;
+    } else {
+        remaining = get_block_device_size(device->fd());
+        if (!remaining) {
+            PLOG(ERROR) << "Could not get block device size for " << device->path();
+            return false;
+        }
+    }
+    while (remaining) {
+        uint64_t to_write = std::min(static_cast<uint64_t>(zeroes.size()), remaining);
+        if (!android::base::WriteFully(device->fd(), zeroes.data(),
+                                       static_cast<size_t>(to_write))) {
+            PLOG(ERROR) << "write failed: " << device->path();
+            return false;
+        }
+        remaining -= to_write;
+    }
+    return true;
+}
+
+bool ImageManager::DeleteBackingImage(const std::string& name) {
+    // For dm-linear devices sitting on top of /data, we cannot risk deleting
+    // the file. The underlying blocks could be reallocated by the filesystem.
+    if (IsImageMapped(name)) {
+        LOG(ERROR) << "Backing image " << name << " is currently mapped to a block device";
+        return false;
+    }
+
+    std::string message;
+    auto header_file = GetImageHeaderPath(name);
+    if (!SplitFiemap::RemoveSplitFiles(header_file, &message)) {
+        // This is fatal, because we don't want to leave these files dangling.
+        LOG(ERROR) << "Error removing image " << name << ": " << message;
+        return false;
+    }
+
+    auto status_file = GetStatusFilePath(name);
+    if (!android::base::RemoveFileIfExists(status_file)) {
+        LOG(ERROR) << "Error removing " << status_file << ": " << message;
+    }
+    return RemoveImageMetadata(metadata_dir_, name);
+}
+
+// Create a block device for an image file, using its extents in its
+// lp_metadata.
+bool ImageManager::MapWithDmLinear(const IPartitionOpener& opener, const std::string& name,
+                                   const std::chrono::milliseconds& timeout_ms, std::string* path) {
+    // :TODO: refresh extents in metadata file until f2fs is fixed.
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return false;
+    }
+
+    auto super = android::fs_mgr::GetMetadataSuperBlockDevice(*metadata.get());
+    auto block_device = android::fs_mgr::GetBlockDevicePartitionName(*super);
+
+    CreateLogicalPartitionParams params = {
+            .block_device = block_device,
+            .metadata = metadata.get(),
+            .partition_name = name,
+            .force_writable = true,
+            .timeout_ms = timeout_ms,
+            .partition_opener = &opener,
+    };
+    if (!CreateLogicalPartition(params, path)) {
+        LOG(ERROR) << "Error creating device-mapper node for image " << name;
+        return false;
+    }
+
+    auto status_string = "dm:" + name;
+    auto status_file = GetStatusFilePath(name);
+    if (!android::base::WriteStringToFile(status_string, status_file)) {
+        PLOG(ERROR) << "Could not write status file: " << status_file;
+        DestroyLogicalPartition(name);
+        return false;
+    }
+    return true;
+}
+
+// Helper to create a loop device for a file.
+static bool CreateLoopDevice(LoopControl& control, const std::string& file,
+                             const std::chrono::milliseconds& timeout_ms, std::string* path) {
+    static constexpr int kOpenFlags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
+    android::base::unique_fd file_fd(open(file.c_str(), kOpenFlags));
+    if (file_fd < 0) {
+        PLOG(ERROR) << "Could not open file: " << file;
+        return false;
+    }
+    if (!control.Attach(file_fd, timeout_ms, path)) {
+        LOG(ERROR) << "Could not create loop device for: " << file;
+        return false;
+    }
+    LOG(INFO) << "Created loop device " << *path << " for file " << file;
+    return true;
+}
+
+class AutoDetachLoopDevices final {
+  public:
+    AutoDetachLoopDevices(LoopControl& control, const std::vector<std::string>& devices)
+        : control_(control), devices_(devices), commit_(false) {}
+
+    ~AutoDetachLoopDevices() {
+        if (commit_) return;
+        for (const auto& device : devices_) {
+            control_.Detach(device);
+        }
+    }
+
+    void Commit() { commit_ = true; }
+
+  private:
+    LoopControl& control_;
+    const std::vector<std::string>& devices_;
+    bool commit_;
+};
+
+// If an image is stored across multiple files, this takes a list of loop
+// devices and joins them together using device-mapper.
+bool ImageManager::MapWithLoopDeviceList(const std::vector<std::string>& device_list,
+                                         const std::string& name,
+                                         const std::chrono::milliseconds& timeout_ms,
+                                         std::string* path) {
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return false;
+    }
+    auto partition = FindPartition(*metadata.get(), name);
+    if (!partition) {
+        LOG(ERROR) << "Could not find image in metadata: " << name;
+        return false;
+    }
+
+    // Since extent lengths are in sector units, the size should be a multiple
+    // of the sector size.
+    uint64_t partition_size = GetPartitionSize(*metadata.get(), *partition);
+    if (partition_size % LP_SECTOR_SIZE != 0) {
+        LOG(ERROR) << "Partition size not sector aligned: " << name << ", " << partition_size
+                   << " bytes";
+        return false;
+    }
+
+    DmTable table;
+
+    uint64_t start_sector = 0;
+    uint64_t sectors_needed = partition_size / LP_SECTOR_SIZE;
+    for (const auto& block_device : device_list) {
+        // The final block device must be == partition_size, otherwise we
+        // can't find the AVB footer on verified partitions.
+        static constexpr int kOpenFlags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
+        unique_fd fd(open(block_device.c_str(), kOpenFlags));
+        if (fd < 0) {
+            PLOG(ERROR) << "Open failed: " << block_device;
+            return false;
+        }
+
+        uint64_t file_size = get_block_device_size(fd);
+        uint64_t file_sectors = file_size / LP_SECTOR_SIZE;
+        uint64_t segment_size = std::min(file_sectors, sectors_needed);
+
+        table.Emplace<DmTargetLinear>(start_sector, segment_size, block_device, 0);
+
+        start_sector += segment_size;
+        sectors_needed -= segment_size;
+        if (sectors_needed == 0) {
+            break;
+        }
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    if (!dm.CreateDevice(name, table, path, timeout_ms)) {
+        LOG(ERROR) << "Could not create device-mapper device over loop set";
+        return false;
+    }
+
+    // Build the status file.
+    std::vector<std::string> lines;
+    lines.emplace_back("dm:" + name);
+    for (const auto& block_device : device_list) {
+        lines.emplace_back("loop:" + block_device);
+    }
+    auto status_message = android::base::Join(lines, "\n");
+    auto status_file = GetStatusFilePath(name);
+    if (!android::base::WriteStringToFile(status_message, status_file)) {
+        PLOG(ERROR) << "Write failed: " << status_file;
+        dm.DeleteDevice(name);
+        return false;
+    }
+    return true;
+}
+
+static bool OptimizeLoopDevices(const std::vector<std::string>& device_list) {
+    for (const auto& device : device_list) {
+        unique_fd fd(open(device.c_str(), O_RDWR | O_CLOEXEC | O_NOFOLLOW));
+        if (fd < 0) {
+            PLOG(ERROR) << "Open failed: " << device;
+            return false;
+        }
+        if (!LoopControl::EnableDirectIo(fd)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// Helper to use one or more loop devices around image files.
+bool ImageManager::MapWithLoopDevice(const std::string& name,
+                                     const std::chrono::milliseconds& timeout_ms,
+                                     std::string* path) {
+    auto image_header = GetImageHeaderPath(name);
+
+    std::vector<std::string> file_list;
+    if (!SplitFiemap::GetSplitFileList(image_header, &file_list)) {
+        LOG(ERROR) << "Could not get image file list";
+        return false;
+    }
+
+    // Map each image file as a loopback device.
+    LoopControl control;
+    std::vector<std::string> loop_devices;
+    AutoDetachLoopDevices auto_detach(control, loop_devices);
+
+    auto start_time = std::chrono::steady_clock::now();
+    for (const auto& file : file_list) {
+        auto now = std::chrono::steady_clock::now();
+        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+
+        std::string loop_device;
+        if (!CreateLoopDevice(control, file, timeout_ms - elapsed, &loop_device)) {
+            break;
+        }
+        loop_devices.emplace_back(loop_device);
+    }
+    if (loop_devices.size() != file_list.size()) {
+        // The number of devices will mismatch if CreateLoopDevice() failed.
+        return false;
+    }
+
+    // If OptimizeLoopDevices fails, we'd use double the memory.
+    if (!OptimizeLoopDevices(loop_devices)) {
+        return false;
+    }
+
+    // If there's only one loop device (by far the most common case, splits
+    // will normally only happen on sdcards with FAT32), then just return that
+    // as the block device. Otherwise, we need to use dm-linear to stitch
+    // together all the loop devices we just created.
+    if (loop_devices.size() > 1) {
+        if (!MapWithLoopDeviceList(loop_devices, name, timeout_ms, path)) {
+            return false;
+        }
+    }
+
+    auto status_message = "loop:" + loop_devices.back();
+    auto status_file = GetStatusFilePath(name);
+    if (!android::base::WriteStringToFile(status_message, status_file)) {
+        PLOG(ERROR) << "Write failed: " << status_file;
+        return false;
+    }
+
+    auto_detach.Commit();
+
+    *path = loop_devices.back();
+    return true;
+}
+
+bool ImageManager::MapImageDevice(const std::string& name,
+                                  const std::chrono::milliseconds& timeout_ms, std::string* path) {
+    if (IsImageMapped(name)) {
+        LOG(ERROR) << "Backing image " << name << " is already mapped";
+        return false;
+    }
+
+    auto image_header = GetImageHeaderPath(name);
+
+    // If there is a device-mapper node wrapping the block device, then we're
+    // able to create another node around it; the dm layer does not carry the
+    // exclusion lock down the stack when a mount occurs.
+    //
+    // If there is no intermediate device-mapper node, then partitions cannot be
+    // opened writable due to sepolicy and exclusivity of having a mounted
+    // filesystem. This should only happen on devices with no encryption, or
+    // devices with FBE and no metadata encryption. For these cases it suffices
+    // to perform normal file writes to /data/gsi (which is unencrypted).
+    std::string block_device;
+    bool can_use_devicemapper;
+    if (!FiemapWriter::GetBlockDeviceForFile(image_header, &block_device, &can_use_devicemapper)) {
+        LOG(ERROR) << "Could not determine block device for " << image_header;
+        return false;
+    }
+
+    if (can_use_devicemapper) {
+        if (!MapWithDmLinear(*partition_opener_.get(), name, timeout_ms, path)) {
+            return false;
+        }
+    } else if (!MapWithLoopDevice(name, timeout_ms, path)) {
+        return false;
+    }
+
+    // Set a property so we remember this is mapped.
+    auto prop_name = GetStatusPropertyName(name);
+    if (!android::base::SetProperty(prop_name, *path)) {
+        UnmapImageDevice(name, true);
+        return false;
+    }
+    return true;
+}
+
+bool ImageManager::MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
+                                            std::string* dev) {
+    std::string ignore_path;
+    if (!MapWithDmLinear(opener, name, {}, &ignore_path)) {
+        return false;
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    if (!dm.GetDeviceString(name, dev)) {
+        return false;
+    }
+    return true;
+}
+
+bool ImageManager::UnmapImageDevice(const std::string& name) {
+    return UnmapImageDevice(name, false);
+}
+
+bool ImageManager::UnmapImageDevice(const std::string& name, bool force) {
+    if (!force && !IsImageMapped(name)) {
+        LOG(ERROR) << "Backing image " << name << " is not mapped";
+        return false;
+    }
+    auto& dm = DeviceMapper::Instance();
+    LoopControl loop;
+
+    std::string status;
+    auto status_file = GetStatusFilePath(name);
+    if (!android::base::ReadFileToString(status_file, &status)) {
+        PLOG(ERROR) << "Read failed: " << status_file;
+        return false;
+    }
+
+    auto lines = android::base::Split(status, "\n");
+    for (const auto& line : lines) {
+        auto pieces = android::base::Split(line, ":");
+        if (pieces.size() != 2) {
+            LOG(ERROR) << "Unknown status line";
+            continue;
+        }
+        if (pieces[0] == "dm") {
+            // Failure to remove a dm node is fatal, since we can't safely
+            // remove the file or loop devices.
+            const auto& name = pieces[1];
+            if (!dm.DeleteDeviceIfExists(name)) {
+                return false;
+            }
+        } else if (pieces[0] == "loop") {
+            // Failure to remove a loop device is not fatal, since we can still
+            // remove the backing file if we want.
+            loop.Detach(pieces[1]);
+        } else {
+            LOG(ERROR) << "Unknown status: " << pieces[0];
+        }
+    }
+
+    std::string message;
+    if (!android::base::RemoveFileIfExists(status_file, &message)) {
+        LOG(ERROR) << "Could not remove " << status_file << ": " << message;
+    }
+
+    auto status_prop = GetStatusPropertyName(name);
+    android::base::SetProperty(status_prop, "");
+    return true;
+}
+
+bool ImageManager::RemoveAllImages() {
+    if (!MetadataExists(metadata_dir_)) {
+        return true;
+    }
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return RemoveAllMetadata(metadata_dir_);
+    }
+
+    bool ok = true;
+    for (const auto& partition : metadata->partitions) {
+        auto partition_name = GetPartitionName(partition);
+        ok &= DeleteBackingImage(partition_name);
+    }
+    return ok && RemoveAllMetadata(metadata_dir_);
+}
+
+bool ImageManager::Validate() {
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return false;
+    }
+
+    for (const auto& partition : metadata->partitions) {
+        auto name = GetPartitionName(partition);
+        auto image_path = GetImageHeaderPath(name);
+        auto fiemap = SplitFiemap::Open(image_path);
+        if (!fiemap || !fiemap->HasPinnedExtents()) {
+            LOG(ERROR) << "Image is missing or was moved: " << image_path;
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ImageManager::DisableImage(const std::string& name) {
+    return AddAttributes(metadata_dir_, name, LP_PARTITION_ATTR_DISABLED);
+}
+
+bool ImageManager::RemoveDisabledImages() {
+    if (!MetadataExists(metadata_dir_)) {
+        return true;
+    }
+
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return false;
+    }
+
+    bool ok = true;
+    for (const auto& partition : metadata->partitions) {
+        if (partition.attributes & LP_PARTITION_ATTR_DISABLED) {
+            ok &= DeleteBackingImage(GetPartitionName(partition));
+        }
+    }
+    return ok;
+}
+
+bool ImageManager::GetMappedImageDevice(const std::string& name, std::string* device) {
+    auto prop_name = GetStatusPropertyName(name);
+    *device = android::base::GetProperty(prop_name, "");
+    if (!device->empty()) {
+        return true;
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    if (dm.GetState(name) == DmDeviceState::INVALID) {
+        return false;
+    }
+    return dm.GetDmDevicePathByName(name, device);
+}
+
+bool ImageManager::MapAllImages(const std::function<bool(std::set<std::string>)>& init) {
+    if (!MetadataExists(metadata_dir_)) {
+        return true;
+    }
+
+    auto metadata = OpenMetadata(metadata_dir_);
+    if (!metadata) {
+        return false;
+    }
+
+    std::set<std::string> devices;
+    for (const auto& name : GetBlockDevicePartitionNames(*metadata.get())) {
+        devices.emplace(name);
+    }
+    if (!init(std::move(devices))) {
+        return false;
+    }
+
+    auto data_device = GetMetadataSuperBlockDevice(*metadata.get());
+    auto data_partition_name = GetBlockDevicePartitionName(*data_device);
+    return CreateLogicalPartitions(*metadata.get(), data_partition_name);
+}
+
+std::unique_ptr<MappedDevice> MappedDevice::Open(IImageManager* manager,
+                                                 const std::chrono::milliseconds& timeout_ms,
+                                                 const std::string& name) {
+    std::string path;
+    if (!manager->MapImageDevice(name, timeout_ms, &path)) {
+        return nullptr;
+    }
+
+    auto device = std::unique_ptr<MappedDevice>(new MappedDevice(manager, name, path));
+    if (device->fd() < 0) {
+        return nullptr;
+    }
+    return device;
+}
+
+MappedDevice::MappedDevice(IImageManager* manager, const std::string& name, const std::string& path)
+    : manager_(manager), name_(name), path_(path) {
+    // The device is already mapped; try and open it.
+    fd_.reset(open(path.c_str(), O_RDWR | O_CLOEXEC));
+}
+
+MappedDevice::~MappedDevice() {
+    fd_ = {};
+    manager_->UnmapImageDevice(name_);
+}
+
+bool IImageManager::UnmapImageIfExists(const std::string& name) {
+    // No lock is needed even though this seems to be vulnerable to TOCTOU. If process A
+    // calls MapImageDevice() while process B calls UnmapImageIfExists(), and MapImageDevice()
+    // happens after process B checks IsImageMapped(), it would be as if MapImageDevice() is called
+    // after process B finishes calling UnmapImageIfExists(), resulting the image to be mapped,
+    // which is a reasonable sequence.
+    if (!IsImageMapped(name)) {
+        return true;
+    }
+    return UnmapImageDevice(name);
+}
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/fs_mgr/libfiemap/image_test.cpp b/fs_mgr/libfiemap/image_test.cpp
new file mode 100644
index 0000000..80c340f
--- /dev/null
+++ b/fs_mgr/libfiemap/image_test.cpp
@@ -0,0 +1,280 @@
+//
+// 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 <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <chrono>
+#include <iostream>
+#include <thread>
+
+#include <android-base/file.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr/file_wait.h>
+#include <gtest/gtest.h>
+#include <libdm/dm.h>
+#include <libfiemap/image_manager.h>
+
+using namespace android::dm;
+using namespace std::literals;
+using android::base::unique_fd;
+using android::fiemap::ImageManager;
+using android::fs_mgr::BlockDeviceInfo;
+using android::fs_mgr::PartitionOpener;
+using android::fs_mgr::WaitForFile;
+
+static std::string gDataPath;
+static std::string gDataMountPath;
+static constexpr char kMetadataPath[] = "/metadata/gsi/test";
+
+static constexpr uint64_t kTestImageSize = 1024 * 1024;
+
+class TestPartitionOpener final : public PartitionOpener {
+  public:
+    android::base::unique_fd Open(const std::string& partition_name, int flags) const override {
+        return PartitionOpener::Open(GetPathForBlockDeviceName(partition_name), flags);
+    }
+    bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const override {
+        return PartitionOpener::GetInfo(GetPathForBlockDeviceName(partition_name), info);
+    }
+    std::string GetDeviceString(const std::string& partition_name) const override {
+        return PartitionOpener::GetDeviceString(GetPathForBlockDeviceName(partition_name));
+    }
+
+  private:
+    static std::string GetPathForBlockDeviceName(const std::string& name) {
+        if (android::base::StartsWith(name, "loop") || android::base::StartsWith(name, "dm-")) {
+            return "/dev/block/"s + name;
+        }
+        return name;
+    }
+};
+
+// This fixture is for tests against the device's native configuration.
+class NativeTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        manager_ = ImageManager::Open(kMetadataPath, gDataPath);
+        ASSERT_NE(manager_, nullptr);
+
+        manager_->set_partition_opener(std::make_unique<TestPartitionOpener>());
+
+        const ::testing::TestInfo* tinfo = ::testing::UnitTest::GetInstance()->current_test_info();
+        base_name_ = tinfo->name();
+    }
+
+    void TearDown() override {
+        manager_->UnmapImageDevice(base_name_);
+        manager_->DeleteBackingImage(base_name_);
+    }
+
+    std::string PropertyName() { return "gsid.mapped_image." + base_name_; }
+
+    std::unique_ptr<ImageManager> manager_;
+    std::string base_name_;
+};
+
+TEST_F(NativeTest, CreateAndMap) {
+    ASSERT_TRUE(manager_->CreateBackingImage(base_name_, kTestImageSize, false, nullptr));
+
+    std::string path;
+    ASSERT_TRUE(manager_->MapImageDevice(base_name_, 5s, &path));
+    ASSERT_TRUE(manager_->IsImageMapped(base_name_));
+    ASSERT_EQ(android::base::GetProperty(PropertyName(), ""), path);
+
+    {
+        unique_fd fd(open(path.c_str(), O_RDWR | O_NOFOLLOW | O_CLOEXEC));
+        ASSERT_GE(fd, 0);
+        ASSERT_EQ(get_block_device_size(fd), kTestImageSize);
+    }
+
+    ASSERT_TRUE(manager_->UnmapImageDevice(base_name_));
+    ASSERT_FALSE(manager_->IsImageMapped(base_name_));
+    ASSERT_EQ(android::base::GetProperty(PropertyName(), ""), "");
+}
+
+TEST_F(NativeTest, DisableImage) {
+    ASSERT_TRUE(manager_->CreateBackingImage(base_name_, kTestImageSize, false, nullptr));
+    ASSERT_TRUE(manager_->BackingImageExists(base_name_));
+    ASSERT_TRUE(manager_->DisableImage(base_name_));
+    ASSERT_TRUE(manager_->RemoveDisabledImages());
+    ASSERT_TRUE(!manager_->BackingImageExists(base_name_));
+}
+
+TEST_F(NativeTest, GetMappedImageDevice) {
+    ASSERT_TRUE(manager_->CreateBackingImage(base_name_, kTestImageSize, false, nullptr));
+
+    std::string path1, path2;
+    ASSERT_TRUE(manager_->MapImageDevice(base_name_, 5s, &path1));
+    ASSERT_TRUE(manager_->GetMappedImageDevice(base_name_, &path2));
+    EXPECT_EQ(path1, path2);
+
+    ASSERT_TRUE(manager_->UnmapImageDevice(base_name_));
+}
+
+// This fixture is for tests against a simulated device environment. Rather
+// than use /data, we create an image and then layer a new filesystem within
+// it. Each test then decides how to mount and create layered images. This
+// allows us to test FBE vs FDE configurations.
+class ImageTest : public ::testing::Test {
+  public:
+    ImageTest() : dm_(DeviceMapper::Instance()) {}
+
+    void SetUp() override {
+        manager_ = ImageManager::Open(kMetadataPath, gDataPath);
+        ASSERT_NE(manager_, nullptr);
+
+        manager_->set_partition_opener(std::make_unique<TestPartitionOpener>());
+
+        submanager_ = ImageManager::Open(kMetadataPath + "/mnt"s, gDataPath + "/mnt"s);
+        ASSERT_NE(submanager_, nullptr);
+
+        submanager_->set_partition_opener(std::make_unique<TestPartitionOpener>());
+
+        // Ensure that metadata is cleared in between runs.
+        submanager_->RemoveAllImages();
+        manager_->RemoveAllImages();
+
+        const ::testing::TestInfo* tinfo = ::testing::UnitTest::GetInstance()->current_test_info();
+        base_name_ = tinfo->name();
+        test_image_name_ = base_name_ + "-base";
+        wrapper_device_name_ = base_name_ + "-wrapper";
+
+        ASSERT_TRUE(manager_->CreateBackingImage(base_name_, kTestImageSize * 16, false, nullptr));
+        ASSERT_TRUE(manager_->MapImageDevice(base_name_, 5s, &base_device_));
+    }
+
+    void TearDown() override {
+        submanager_->UnmapImageDevice(test_image_name_);
+        umount(gDataMountPath.c_str());
+        dm_.DeleteDeviceIfExists(wrapper_device_name_);
+        manager_->UnmapImageDevice(base_name_);
+        manager_->DeleteBackingImage(base_name_);
+    }
+
+  protected:
+    bool DoFormat(const std::string& device) {
+        // clang-format off
+        std::vector<std::string> mkfs_args = {
+            "/system/bin/mke2fs",
+            "-F",
+            "-b 4096",
+            "-t ext4",
+            "-m 0",
+            "-O has_journal",
+            device,
+            ">/dev/null",
+            "2>/dev/null",
+            "</dev/null",
+        };
+        // clang-format on
+        auto command = android::base::Join(mkfs_args, " ");
+        return system(command.c_str()) == 0;
+    }
+
+    std::unique_ptr<ImageManager> manager_;
+    std::unique_ptr<ImageManager> submanager_;
+
+    DeviceMapper& dm_;
+    std::string base_name_;
+    std::string base_device_;
+    std::string test_image_name_;
+    std::string wrapper_device_name_;
+};
+
+TEST_F(ImageTest, DirectMount) {
+    ASSERT_TRUE(DoFormat(base_device_));
+    ASSERT_EQ(mount(base_device_.c_str(), gDataMountPath.c_str(), "ext4", 0, nullptr), 0);
+    ASSERT_TRUE(submanager_->CreateBackingImage(test_image_name_, kTestImageSize, false, nullptr));
+
+    std::string path;
+    ASSERT_TRUE(submanager_->MapImageDevice(test_image_name_, 5s, &path));
+    ASSERT_TRUE(android::base::StartsWith(path, "/dev/block/loop"));
+}
+
+TEST_F(ImageTest, IndirectMount) {
+    // Create a simple wrapper around the base device that we'll mount from
+    // instead. This will simulate the code paths for dm-crypt/default-key/bow
+    // and force us to use device-mapper rather than loop devices.
+    uint64_t device_size = 0;
+    {
+        unique_fd fd(open(base_device_.c_str(), O_RDWR | O_CLOEXEC));
+        ASSERT_GE(fd, 0);
+        device_size = get_block_device_size(fd);
+        ASSERT_EQ(device_size, kTestImageSize * 16);
+    }
+    uint64_t num_sectors = device_size / 512;
+
+    auto& dm = DeviceMapper::Instance();
+
+    DmTable table;
+    table.Emplace<DmTargetLinear>(0, num_sectors, base_device_, 0);
+    ASSERT_TRUE(dm.CreateDevice(wrapper_device_name_, table));
+
+    // Format and mount.
+    std::string wrapper_device;
+    ASSERT_TRUE(dm.GetDmDevicePathByName(wrapper_device_name_, &wrapper_device));
+    ASSERT_TRUE(WaitForFile(wrapper_device, 5s));
+    ASSERT_TRUE(DoFormat(wrapper_device));
+    ASSERT_EQ(mount(wrapper_device.c_str(), gDataMountPath.c_str(), "ext4", 0, nullptr), 0);
+
+    ASSERT_TRUE(submanager_->CreateBackingImage(test_image_name_, kTestImageSize, false, nullptr));
+
+    std::set<std::string> backing_devices;
+    auto init = [&](std::set<std::string> devices) -> bool {
+        backing_devices = std::move(devices);
+        return true;
+    };
+
+    std::string path;
+    ASSERT_TRUE(submanager_->MapImageDevice(test_image_name_, 5s, &path));
+    ASSERT_TRUE(android::base::StartsWith(path, "/dev/block/dm-"));
+    ASSERT_TRUE(submanager_->UnmapImageDevice(test_image_name_));
+    ASSERT_TRUE(submanager_->MapAllImages(init));
+    ASSERT_FALSE(backing_devices.empty());
+    ASSERT_TRUE(submanager_->UnmapImageDevice(test_image_name_));
+}
+
+bool Mkdir(const std::string& path) {
+    if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
+        std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
+        return false;
+    }
+    return true;
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    if (argc >= 2) {
+        gDataPath = argv[1];
+    } else {
+        gDataPath = "/data/gsi/test";
+    }
+    gDataMountPath = gDataPath + "/mnt"s;
+
+    if (!Mkdir(gDataPath) || !Mkdir(kMetadataPath) || !Mkdir(gDataMountPath) ||
+        !Mkdir(kMetadataPath + "/mnt"s)) {
+        return 1;
+    }
+    return RUN_ALL_TESTS();
+}
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h b/fs_mgr/libfiemap/include/libfiemap/fiemap_writer.h
similarity index 83%
rename from fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
rename to fs_mgr/libfiemap/include/libfiemap/fiemap_writer.h
index 9486122..c692265 100644
--- a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
+++ b/fs_mgr/libfiemap/include/libfiemap/fiemap_writer.h
@@ -28,7 +28,7 @@
 #include <android-base/unique_fd.h>
 
 namespace android {
-namespace fiemap_writer {
+namespace fiemap {
 
 class FiemapWriter;
 using FiemapUniquePtr = std::unique_ptr<FiemapWriter>;
@@ -60,10 +60,17 @@
     // FiemapWriter::Open).
     static bool HasPinnedExtents(const std::string& file_path);
 
-    // Returns the underlying block device of a file. This will look past device-mapper layers.
-    // If an intermediate device-mapper layer would not maintain a 1:1 mapping (i.e. is a non-
-    // trivial dm-linear), then this will fail. If device-mapper nodes are encountered, then
-    // |uses_dm| will be set to true.
+    // Returns the underlying block device of a file. This will look past device-mapper layers
+    // as long as each layer would not change block mappings (i.e., dm-crypt, dm-bow, and dm-
+    // default-key tables are okay; dm-linear is not). If a mapping such as dm-linear is found,
+    // it will be returned in place of any physical block device.
+    //
+    // It is the caller's responsibility to check whether the returned block device is acceptable.
+    // Gsid, for example, will only accept /dev/block/by-name/userdata as the bottom device.
+    // Callers can check the device name (dm- or loop prefix), inspect sysfs, or compare the major
+    // number against a boot device.
+    //
+    // If device-mapper nodes were encountered, then |uses_dm| will be set to true.
     static bool GetBlockDeviceForFile(const std::string& file_path, std::string* bdev_path,
                                       bool* uses_dm = nullptr);
 
@@ -107,5 +114,5 @@
     FiemapWriter() = default;
 };
 
-}  // namespace fiemap_writer
+}  // namespace fiemap
 }  // namespace android
diff --git a/fs_mgr/libfiemap/include/libfiemap/image_manager.h b/fs_mgr/libfiemap/include/libfiemap/image_manager.h
new file mode 100644
index 0000000..7b907c0
--- /dev/null
+++ b/fs_mgr/libfiemap/include/libfiemap/image_manager.h
@@ -0,0 +1,213 @@
+//
+// 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 <stdint.h>
+
+#include <chrono>
+#include <functional>
+#include <memory>
+#include <set>
+#include <string>
+
+#include <android-base/unique_fd.h>
+#include <liblp/partition_opener.h>
+
+namespace android {
+namespace fiemap {
+
+class IImageManager {
+  public:
+    using IPartitionOpener = android::fs_mgr::IPartitionOpener;
+
+    virtual ~IImageManager() {}
+
+    // When linking to libfiemap_binder, the Open() call will use binder.
+    // Otherwise, the Open() call will use the ImageManager implementation
+    // below.
+    static std::unique_ptr<IImageManager> Open(const std::string& dir_prefix,
+                                               const std::chrono::milliseconds& timeout_ms);
+
+    // Flags for CreateBackingImage().
+    static constexpr int CREATE_IMAGE_DEFAULT = 0x0;
+    static constexpr int CREATE_IMAGE_READONLY = 0x1;
+    static constexpr int CREATE_IMAGE_ZERO_FILL = 0x2;
+
+    // Create an image that can be mapped as a block-device. If |force_zero_fill|
+    // is true, the image will be zero-filled. Otherwise, the initial content
+    // of the image is undefined. If zero-fill is requested, and the operation
+    // cannot be completed, the image will be deleted and this function will
+    // return false.
+    virtual bool CreateBackingImage(const std::string& name, uint64_t size, int flags) = 0;
+
+    // Delete an image created with CreateBackingImage. Its entry will be
+    // removed from the associated lp_metadata file.
+    virtual bool DeleteBackingImage(const std::string& name) = 0;
+
+    // Create a block device for an image previously created with
+    // CreateBackingImage. This will wait for at most |timeout_ms| milliseconds
+    // for |path| to be available, and will return false if not available in
+    // the requested time. If |timeout_ms| is zero, this is NOT guaranteed to
+    // return true. A timeout of 10s is recommended.
+    //
+    // Note that snapshots created with a readonly flag are always mapped
+    // writable. The flag is persisted in the lp_metadata file however, so if
+    // fs_mgr::CreateLogicalPartition(s) is used, the flag will be respected.
+    virtual bool MapImageDevice(const std::string& name,
+                                const std::chrono::milliseconds& timeout_ms, std::string* path) = 0;
+
+    // Unmap a block device previously mapped with mapBackingImage.
+    virtual bool UnmapImageDevice(const std::string& name) = 0;
+
+    // Returns true whether the named backing image exists.
+    virtual bool BackingImageExists(const std::string& name) = 0;
+
+    // Returns true if the specified image is mapped to a device.
+    virtual bool IsImageMapped(const std::string& name) = 0;
+
+    // Map an image using device-mapper. This is not available over binder, and
+    // is intended only for first-stage init. The returned device is a major:minor
+    // device string.
+    virtual bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
+                                          std::string* dev) = 0;
+
+    // If an image was mapped, return the path to its device. Otherwise, return
+    // false. Errors are not reported in this case, calling IsImageMapped is
+    // not necessary.
+    virtual bool GetMappedImageDevice(const std::string& name, std::string* device) = 0;
+
+    // Map all images owned by this manager. This is only intended to be used
+    // during first-stage init, and as such, it does not provide a timeout
+    // (meaning libdm races can't be resolved, as ueventd is not available),
+    // and is not available over binder.
+    //
+    // The callback provided is given the list of dependent block devices.
+    virtual bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) = 0;
+
+    // Mark an image as disabled. This is useful for marking an image as
+    // will-be-deleted in recovery, since recovery cannot mount /data.
+    //
+    // This is not available in binder, since it is intended for recovery.
+    // When binder is available, images can simply be removed.
+    virtual bool DisableImage(const std::string& name) = 0;
+
+    // Remove all images that been marked as disabled.
+    virtual bool RemoveDisabledImages() = 0;
+
+    // Get all backing image names.
+    virtual std::vector<std::string> GetAllBackingImages() = 0;
+
+    // Writes |bytes| zeros to |name| file. If |bytes| is 0, then the
+    // whole file if filled with zeros.
+    virtual bool ZeroFillNewImage(const std::string& name, uint64_t bytes) = 0;
+
+    // Find and remove all images and metadata for this manager.
+    virtual bool RemoveAllImages() = 0;
+
+    virtual bool UnmapImageIfExists(const std::string& name);
+};
+
+class ImageManager final : public IImageManager {
+  public:
+    // Return an ImageManager for the given metadata and data directories. Both
+    // directories must already exist.
+    static std::unique_ptr<ImageManager> Open(const std::string& metadata_dir,
+                                              const std::string& data_dir);
+
+    // Helper function that derives the metadata and data dirs given a single
+    // prefix.
+    static std::unique_ptr<ImageManager> Open(const std::string& dir_prefix);
+
+    // Methods that must be implemented from IImageManager.
+    bool CreateBackingImage(const std::string& name, uint64_t size, int flags) override;
+    bool DeleteBackingImage(const std::string& name) override;
+    bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
+                        std::string* path) override;
+    bool UnmapImageDevice(const std::string& name) override;
+    bool BackingImageExists(const std::string& name) override;
+    bool IsImageMapped(const std::string& name) override;
+    bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
+                                  std::string* dev) override;
+    bool RemoveAllImages() override;
+    bool DisableImage(const std::string& name) override;
+    bool RemoveDisabledImages() override;
+    bool GetMappedImageDevice(const std::string& name, std::string* device) override;
+    bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override;
+
+    std::vector<std::string> GetAllBackingImages();
+    // Same as CreateBackingImage, but provides a progress notification.
+    bool CreateBackingImage(const std::string& name, uint64_t size, int flags,
+                            std::function<bool(uint64_t, uint64_t)>&& on_progress);
+
+    // Returns true if the named partition exists. This does not check the
+    // consistency of the backing image/data file.
+    bool PartitionExists(const std::string& name);
+
+    // Validates that all images still have pinned extents. This will be removed
+    // once b/134588268 is fixed.
+    bool Validate();
+
+    void set_partition_opener(std::unique_ptr<IPartitionOpener>&& opener);
+
+    // Writes |bytes| zeros at the beginning of the passed image
+    bool ZeroFillNewImage(const std::string& name, uint64_t bytes);
+
+  private:
+    ImageManager(const std::string& metadata_dir, const std::string& data_dir);
+    std::string GetImageHeaderPath(const std::string& name);
+    std::string GetStatusFilePath(const std::string& image_name);
+    bool MapWithLoopDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
+                           std::string* path);
+    bool MapWithLoopDeviceList(const std::vector<std::string>& device_list, const std::string& name,
+                               const std::chrono::milliseconds& timeout_ms, std::string* path);
+    bool MapWithDmLinear(const IPartitionOpener& opener, const std::string& name,
+                         const std::chrono::milliseconds& timeout_ms, std::string* path);
+    bool UnmapImageDevice(const std::string& name, bool force);
+
+    ImageManager(const ImageManager&) = delete;
+    ImageManager& operator=(const ImageManager&) = delete;
+    ImageManager& operator=(ImageManager&&) = delete;
+    ImageManager(ImageManager&&) = delete;
+
+    std::string metadata_dir_;
+    std::string data_dir_;
+    std::unique_ptr<IPartitionOpener> partition_opener_;
+};
+
+// RAII helper class for mapping and opening devices with an ImageManager.
+class MappedDevice final {
+  public:
+    static std::unique_ptr<MappedDevice> Open(IImageManager* manager,
+                                              const std::chrono::milliseconds& timeout_ms,
+                                              const std::string& name);
+
+    ~MappedDevice();
+
+    int fd() const { return fd_; }
+    const std::string& path() const { return path_; }
+
+  protected:
+    MappedDevice(IImageManager* manager, const std::string& name, const std::string& path);
+
+    IImageManager* manager_;
+    std::string name_;
+    std::string path_;
+    android::base::unique_fd fd_;
+};
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h b/fs_mgr/libfiemap/include/libfiemap/split_fiemap_writer.h
similarity index 97%
rename from fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h
rename to fs_mgr/libfiemap/include/libfiemap/split_fiemap_writer.h
index 7b977e1..feffb3d 100644
--- a/fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h
+++ b/fs_mgr/libfiemap/include/libfiemap/split_fiemap_writer.h
@@ -28,7 +28,7 @@
 #include "fiemap_writer.h"
 
 namespace android {
-namespace fiemap_writer {
+namespace fiemap {
 
 // Wrapper around FiemapWriter that is able to split images across files if
 // necessary.
@@ -93,5 +93,5 @@
     android::base::unique_fd cursor_fd_;
 };
 
-}  // namespace fiemap_writer
+}  // namespace fiemap
 }  // namespace android
diff --git a/fs_mgr/libfiemap/metadata.cpp b/fs_mgr/libfiemap/metadata.cpp
new file mode 100644
index 0000000..ea1f508
--- /dev/null
+++ b/fs_mgr/libfiemap/metadata.cpp
@@ -0,0 +1,214 @@
+//
+// 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 "metadata.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <liblp/builder.h>
+
+#include "utility.h"
+
+namespace android {
+namespace fiemap {
+
+using namespace android::fs_mgr;
+
+static constexpr uint32_t kMaxMetadataSize = 256 * 1024;
+
+std::string GetMetadataFile(const std::string& metadata_dir) {
+    return JoinPaths(metadata_dir, "lp_metadata");
+}
+
+bool MetadataExists(const std::string& metadata_dir) {
+    auto metadata_file = GetMetadataFile(metadata_dir);
+    return access(metadata_file.c_str(), F_OK) == 0;
+}
+
+std::unique_ptr<LpMetadata> OpenMetadata(const std::string& metadata_dir) {
+    auto metadata_file = GetMetadataFile(metadata_dir);
+    auto metadata = ReadFromImageFile(metadata_file);
+    if (!metadata) {
+        LOG(ERROR) << "Could not read metadata file " << metadata_file;
+        return nullptr;
+    }
+    return metadata;
+}
+
+// :TODO: overwrite on create if open fails
+std::unique_ptr<MetadataBuilder> OpenOrCreateMetadata(const std::string& metadata_dir,
+                                                      SplitFiemap* file) {
+    auto metadata_file = GetMetadataFile(metadata_dir);
+
+    PartitionOpener opener;
+    std::unique_ptr<MetadataBuilder> builder;
+    if (access(metadata_file.c_str(), R_OK)) {
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "access " << metadata_file << " failed:";
+            return nullptr;
+        }
+
+        auto data_device = GetDevicePathForFile(file);
+
+        BlockDeviceInfo device_info;
+        if (!opener.GetInfo(data_device, &device_info)) {
+            LOG(ERROR) << "Could not read partition: " << data_device;
+            return nullptr;
+        }
+
+        std::vector<BlockDeviceInfo> block_devices = {device_info};
+        auto super_name = android::base::Basename(data_device);
+        builder = MetadataBuilder::New(block_devices, super_name, kMaxMetadataSize, 1);
+    } else {
+        auto metadata = OpenMetadata(metadata_dir);
+        if (!metadata) {
+            return nullptr;
+        }
+        builder = MetadataBuilder::New(*metadata.get(), &opener);
+    }
+
+    if (!builder) {
+        LOG(ERROR) << "Could not create metadata builder";
+        return nullptr;
+    }
+    return builder;
+}
+
+bool SaveMetadata(MetadataBuilder* builder, const std::string& metadata_dir) {
+    auto exported = builder->Export();
+    if (!exported) {
+        LOG(ERROR) << "Unable to export new metadata";
+        return false;
+    }
+
+    // If there are no more partitions in the metadata, just delete the file.
+    auto metadata_file = GetMetadataFile(metadata_dir);
+    if (exported->partitions.empty() && android::base::RemoveFileIfExists(metadata_file)) {
+        return true;
+    }
+    if (!WriteToImageFile(metadata_file, *exported.get())) {
+        LOG(ERROR) << "Unable to save new metadata";
+        return false;
+    }
+    return true;
+}
+
+bool RemoveAllMetadata(const std::string& dir) {
+    auto metadata_file = GetMetadataFile(dir);
+    return android::base::RemoveFileIfExists(metadata_file);
+}
+
+bool FillPartitionExtents(MetadataBuilder* builder, Partition* partition, SplitFiemap* file,
+                          uint64_t partition_size) {
+    auto block_device = android::base::Basename(GetDevicePathForFile(file));
+
+    uint64_t sectors_needed = partition_size / LP_SECTOR_SIZE;
+    for (const auto& extent : file->extents()) {
+        if (extent.fe_length % LP_SECTOR_SIZE != 0) {
+            LOG(ERROR) << "Extent is not sector-aligned: " << extent.fe_length;
+            return false;
+        }
+        if (extent.fe_physical % LP_SECTOR_SIZE != 0) {
+            LOG(ERROR) << "Extent physical sector is not sector-aligned: " << extent.fe_physical;
+            return false;
+        }
+
+        uint64_t num_sectors =
+                std::min(static_cast<uint64_t>(extent.fe_length / LP_SECTOR_SIZE), sectors_needed);
+        if (!num_sectors || !sectors_needed) {
+            // This should never happen, but we include it just in case. It would
+            // indicate that the last filesystem block had multiple extents.
+            LOG(WARNING) << "FiemapWriter allocated extra blocks";
+            break;
+        }
+
+        uint64_t physical_sector = extent.fe_physical / LP_SECTOR_SIZE;
+        if (!builder->AddLinearExtent(partition, block_device, num_sectors, physical_sector)) {
+            LOG(ERROR) << "Could not add extent to lp metadata";
+            return false;
+        }
+
+        sectors_needed -= num_sectors;
+    }
+    return true;
+}
+
+bool RemoveImageMetadata(const std::string& metadata_dir, const std::string& partition_name) {
+    if (!MetadataExists(metadata_dir)) {
+        return true;
+    }
+    auto metadata = OpenMetadata(metadata_dir);
+    if (!metadata) {
+        return false;
+    }
+
+    PartitionOpener opener;
+    auto builder = MetadataBuilder::New(*metadata.get(), &opener);
+    if (!builder) {
+        return false;
+    }
+    builder->RemovePartition(partition_name);
+    return SaveMetadata(builder.get(), metadata_dir);
+}
+
+bool UpdateMetadata(const std::string& metadata_dir, const std::string& partition_name,
+                    SplitFiemap* file, uint64_t partition_size, bool readonly) {
+    auto builder = OpenOrCreateMetadata(metadata_dir, file);
+    if (!builder) {
+        return false;
+    }
+    auto partition = builder->FindPartition(partition_name);
+    if (!partition) {
+        int attrs = 0;
+        if (readonly) attrs |= LP_PARTITION_ATTR_READONLY;
+
+        if ((partition = builder->AddPartition(partition_name, attrs)) == nullptr) {
+            LOG(ERROR) << "Could not add partition " << partition_name << " to metadata";
+            return false;
+        }
+    }
+    partition->RemoveExtents();
+
+    if (!FillPartitionExtents(builder.get(), partition, file, partition_size)) {
+        return false;
+    }
+    return SaveMetadata(builder.get(), metadata_dir);
+}
+
+bool AddAttributes(const std::string& metadata_dir, const std::string& partition_name,
+                   uint32_t attributes) {
+    auto metadata = OpenMetadata(metadata_dir);
+    if (!metadata) {
+        return false;
+    }
+    auto builder = MetadataBuilder::New(*metadata.get());
+    if (!builder) {
+        return false;
+    }
+    auto partition = builder->FindPartition(partition_name);
+    if (!partition) {
+        return false;
+    }
+    partition->set_attributes(partition->attributes() | attributes);
+    return SaveMetadata(builder.get(), metadata_dir);
+}
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/fs_mgr/libfiemap/metadata.h b/fs_mgr/libfiemap/metadata.h
new file mode 100644
index 0000000..4eb3ad5
--- /dev/null
+++ b/fs_mgr/libfiemap/metadata.h
@@ -0,0 +1,38 @@
+//
+// 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 <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include <libfiemap/split_fiemap_writer.h>
+#include <liblp/liblp.h>
+
+namespace android {
+namespace fiemap {
+
+bool MetadataExists(const std::string& metadata_dir);
+std::unique_ptr<android::fs_mgr::LpMetadata> OpenMetadata(const std::string& metadata_dir);
+bool UpdateMetadata(const std::string& metadata_dir, const std::string& partition_name,
+                    SplitFiemap* file, uint64_t partition_size, bool readonly);
+bool AddAttributes(const std::string& metadata_dir, const std::string& partition_name,
+                   uint32_t attributes);
+bool RemoveImageMetadata(const std::string& metadata_dir, const std::string& partition_name);
+bool RemoveAllMetadata(const std::string& dir);
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/libmeminfo/libdmabufinfo/tools/Android.bp b/fs_mgr/libfiemap/passthrough.cpp
similarity index 61%
copy from libmeminfo/libdmabufinfo/tools/Android.bp
copy to fs_mgr/libfiemap/passthrough.cpp
index 224b68e..1ccd9a0 100644
--- a/libmeminfo/libdmabufinfo/tools/Android.bp
+++ b/fs_mgr/libfiemap/passthrough.cpp
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2019 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,20 +12,18 @@
 // 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_binary {
-    name: "dmabuf_dump",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
+#include <libfiemap/image_manager.h>
 
-    srcs: ["dmabuf_dump.cpp"],
-    shared_libs: [
-        "libbase",
-    ],
-    static_libs: [
-        "libdmabufinfo",
-    ],
-    product_specific: true,
-}
\ No newline at end of file
+namespace android {
+namespace fiemap {
+
+std::unique_ptr<IImageManager> IImageManager::Open(const std::string& dir_prefix,
+                                                   const std::chrono::milliseconds& timeout_ms) {
+    (void)timeout_ms;
+    return ImageManager::Open(dir_prefix);
+}
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp b/fs_mgr/libfiemap/split_fiemap_writer.cpp
similarity index 95%
rename from fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
rename to fs_mgr/libfiemap/split_fiemap_writer.cpp
index a0ccc10..cc54f20 100644
--- a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/split_fiemap_writer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <libfiemap_writer/split_fiemap_writer.h>
+#include <libfiemap/split_fiemap_writer.h>
 
 #include <fcntl.h>
 #include <stdint.h>
@@ -35,7 +35,7 @@
 #include "utility.h"
 
 namespace android {
-namespace fiemap_writer {
+namespace fiemap {
 
 using android::base::unique_fd;
 
@@ -58,6 +58,9 @@
         }
     }
 
+    // Remove any existing file.
+    RemoveSplitFiles(file_path);
+
     // Call |progress| only when the total percentage would significantly change.
     int permille = -1;
     uint64_t total_bytes_written = 0;
@@ -95,7 +98,10 @@
         // To make sure the alignment doesn't create too much inconsistency, we
         // account the *actual* size, not the requested size.
         total_bytes_written += writer->size();
-        remaining_bytes -= writer->size();
+
+        // writer->size() is block size aligned and could be bigger than remaining_bytes
+        // If remaining_bytes is bigger, set remaining_bytes to 0 to avoid underflow error.
+        remaining_bytes = remaining_bytes > writer->size() ? (remaining_bytes - writer->size()) : 0;
 
         out->AddFile(std::move(writer));
     }
@@ -293,5 +299,5 @@
     return files_[0]->bdev_path();
 }
 
-}  // namespace fiemap_writer
+}  // namespace fiemap
 }  // namespace android
diff --git a/fs_mgr/libfiemap_writer/testdata/file_32k b/fs_mgr/libfiemap/testdata/file_32k
similarity index 100%
rename from fs_mgr/libfiemap_writer/testdata/file_32k
rename to fs_mgr/libfiemap/testdata/file_32k
Binary files differ
diff --git a/fs_mgr/libfiemap_writer/testdata/file_4k b/fs_mgr/libfiemap/testdata/file_4k
similarity index 100%
rename from fs_mgr/libfiemap_writer/testdata/file_4k
rename to fs_mgr/libfiemap/testdata/file_4k
Binary files differ
diff --git a/fs_mgr/libfiemap_writer/testdata/unaligned_file b/fs_mgr/libfiemap/testdata/unaligned_file
similarity index 100%
rename from fs_mgr/libfiemap_writer/testdata/unaligned_file
rename to fs_mgr/libfiemap/testdata/unaligned_file
Binary files differ
diff --git a/fs_mgr/libfiemap/utility.cpp b/fs_mgr/libfiemap/utility.cpp
new file mode 100644
index 0000000..955e544
--- /dev/null
+++ b/fs_mgr/libfiemap/utility.cpp
@@ -0,0 +1,171 @@
+/*
+ * 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 "utility.h"
+
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <libfiemap/fiemap_writer.h>
+
+namespace android {
+namespace fiemap {
+
+using namespace std::string_literals;
+using android::base::unique_fd;
+
+static constexpr char kUserdataDevice[] = "/dev/block/by-name/userdata";
+
+uint64_t DetermineMaximumFileSize(const std::string& file_path) {
+    // Create the smallest file possible (one block).
+    auto writer = FiemapWriter::Open(file_path, 1);
+    if (!writer) {
+        return 0;
+    }
+
+    uint64_t result = 0;
+    switch (writer->fs_type()) {
+        case EXT4_SUPER_MAGIC:
+            // The minimum is 16GiB, so just report that. If we wanted we could parse the
+            // superblock and figure out if 64-bit support is enabled.
+            result = 17179869184ULL;
+            break;
+        case F2FS_SUPER_MAGIC:
+            // Formula is from https://www.kernel.org/doc/Documentation/filesystems/f2fs.txt
+            // 4KB * (923 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
+            result = 4329690886144ULL;
+            break;
+        case MSDOS_SUPER_MAGIC:
+            // 4GB-1, which we want aligned to the block size.
+            result = 4294967295;
+            result -= (result % writer->block_size());
+            break;
+        default:
+            LOG(ERROR) << "Unknown file system type: " << writer->fs_type();
+            break;
+    }
+
+    // Close and delete the temporary file.
+    writer = nullptr;
+    unlink(file_path.c_str());
+
+    return result;
+}
+
+// Given a SplitFiemap, this returns a device path that will work during first-
+// stage init (i.e., its path can be found by InitRequiredDevices).
+std::string GetDevicePathForFile(SplitFiemap* file) {
+    auto bdev_path = file->bdev_path();
+
+    struct stat userdata, given;
+    if (!stat(bdev_path.c_str(), &given) && !stat(kUserdataDevice, &userdata)) {
+        if (S_ISBLK(given.st_mode) && S_ISBLK(userdata.st_mode) &&
+            given.st_rdev == userdata.st_rdev) {
+            return kUserdataDevice;
+        }
+    }
+    return bdev_path;
+}
+
+std::string JoinPaths(const std::string& dir, const std::string& file) {
+    if (android::base::EndsWith(dir, "/")) {
+        return dir + file;
+    }
+    return dir + "/" + file;
+}
+
+bool F2fsPinBeforeAllocate(int file_fd, bool* supported) {
+    struct stat st;
+    if (fstat(file_fd, &st) < 0) {
+        PLOG(ERROR) << "stat failed";
+        return false;
+    }
+    std::string bdev;
+    if (!BlockDeviceToName(major(st.st_dev), minor(st.st_dev), &bdev)) {
+        LOG(ERROR) << "Failed to get block device name for " << major(st.st_dev) << ":"
+                   << minor(st.st_dev);
+        return false;
+    }
+
+    std::string contents;
+    std::string feature_file = "/sys/fs/f2fs/" + bdev + "/features";
+    if (!android::base::ReadFileToString(feature_file, &contents)) {
+        PLOG(ERROR) << "read failed: " << feature_file;
+        return false;
+    }
+    contents = android::base::Trim(contents);
+
+    auto features = android::base::Split(contents, ", ");
+    auto iter = std::find(features.begin(), features.end(), "pin_file"s);
+    *supported = (iter != features.end());
+    return true;
+}
+
+bool BlockDeviceToName(uint32_t major, uint32_t minor, std::string* bdev_name) {
+    // The symlinks in /sys/dev/block point to the block device node under /sys/device/..
+    // The directory name in the target corresponds to the name of the block device. We use
+    // that to extract the block device name.
+    // e.g for block device name 'ram0', there exists a symlink named '1:0' in /sys/dev/block as
+    // follows.
+    //    1:0 -> ../../devices/virtual/block/ram0
+    std::string sysfs_path = ::android::base::StringPrintf("/sys/dev/block/%u:%u", major, minor);
+    std::string sysfs_bdev;
+
+    if (!::android::base::Readlink(sysfs_path, &sysfs_bdev)) {
+        PLOG(ERROR) << "Failed to read link at: " << sysfs_path;
+        return false;
+    }
+
+    *bdev_name = ::android::base::Basename(sysfs_bdev);
+    // Paranoid sanity check to make sure we just didn't get the
+    // input in return as-is.
+    if (sysfs_bdev == *bdev_name) {
+        LOG(ERROR) << "Malformed symlink for block device: " << sysfs_bdev;
+        return false;
+    }
+
+    return true;
+}
+
+bool FilesystemHasReliablePinning(const std::string& file, bool* supported) {
+    struct statfs64 sfs;
+    if (statfs64(file.c_str(), &sfs)) {
+        PLOG(ERROR) << "statfs failed: " << file;
+        return false;
+    }
+    if (sfs.f_type != F2FS_SUPER_MAGIC) {
+        *supported = true;
+        return true;
+    }
+
+    unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
+    if (fd < 0) {
+        PLOG(ERROR) << "open failed: " << file;
+        return false;
+    }
+    return F2fsPinBeforeAllocate(fd, supported);
+}
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/fs_mgr/libfiemap/utility.h b/fs_mgr/libfiemap/utility.h
new file mode 100644
index 0000000..24ebc57
--- /dev/null
+++ b/fs_mgr/libfiemap/utility.h
@@ -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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+
+#include <libfiemap/split_fiemap_writer.h>
+
+namespace android {
+namespace fiemap {
+
+// Given a file that will be created, determine the maximum size its containing
+// filesystem allows. Note this is a theoretical maximum size; free space is
+// ignored entirely.
+uint64_t DetermineMaximumFileSize(const std::string& file_path);
+
+// Given a SplitFiemap, this returns a device path that will work during first-
+// stage init (i.e., its path can be found by InitRequiredDevices).
+std::string GetDevicePathForFile(android::fiemap::SplitFiemap* file);
+
+// Combine two path components into a single path.
+std::string JoinPaths(const std::string& dir, const std::string& file);
+
+// Given a file within an F2FS filesystem, return whether or not the filesystem
+// supports the "pin_file" feature, which requires pinning before fallocation.
+bool F2fsPinBeforeAllocate(int file_fd, bool* supported);
+
+// Given a major/minor device number, return its canonical name such that
+// /dev/block/<name> resolves to the device.
+bool BlockDeviceToName(uint32_t major, uint32_t minor, std::string* bdev_name);
+
+// This is the same as F2fsPinBeforeAllocate, however, it will return true
+// (and supported = true) for non-f2fs filesystems. It is intended to be used
+// in conjunction with ImageManager to reject image requests for reliable use
+// cases (such as snapshots or adb remount).
+bool FilesystemHasReliablePinning(const std::string& file, bool* supported);
+
+}  // namespace fiemap
+}  // namespace android
diff --git a/fs_mgr/libfiemap_writer/.clang-format b/fs_mgr/libfiemap_writer/.clang-format
deleted file mode 120000
index 8b770a1..0000000
--- a/fs_mgr/libfiemap_writer/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../../.clang-format-4
\ No newline at end of file
diff --git a/fs_mgr/libfiemap_writer/Android.bp b/fs_mgr/libfiemap_writer/Android.bp
deleted file mode 100644
index 32fc3d2..0000000
--- a/fs_mgr/libfiemap_writer/Android.bp
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// 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.
-//
-
-cc_library_static {
-    name: "libfiemap_writer",
-    defaults: ["fs_mgr_defaults"],
-    recovery_available: true,
-    export_include_dirs: ["include"],
-    cflags: [
-        "-D_FILE_OFFSET_BITS=64",
-    ],
-
-    srcs: [
-        "fiemap_writer.cpp",
-        "split_fiemap_writer.cpp",
-        "utility.cpp",
-    ],
-
-    static_libs: [
-        "libext4_utils",
-    ],
-
-    header_libs: [
-        "libbase_headers",
-        "liblog_headers",
-    ],
-}
-
-cc_test {
-    name: "fiemap_writer_test",
-    cflags: [
-        "-D_FILE_OFFSET_BITS=64",
-    ],
-    static_libs: [
-        "libbase",
-        "libdm",
-        "libfiemap_writer",
-        "liblog",
-    ],
-
-    data: [
-        "testdata/unaligned_file",
-        "testdata/file_4k",
-        "testdata/file_32k",
-    ],
-
-    srcs: [
-        "fiemap_writer_test.cpp",
-    ],
-}
diff --git a/fs_mgr/libfiemap_writer/Android.mk b/fs_mgr/libfiemap_writer/Android.mk
deleted file mode 100644
index 3c07b8e..0000000
--- a/fs_mgr/libfiemap_writer/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := VtsFiemapWriterTest
--include test/vts/tools/build/Android.host_config.mk
diff --git a/fs_mgr/libfiemap_writer/utility.cpp b/fs_mgr/libfiemap_writer/utility.cpp
deleted file mode 100644
index 192ec16..0000000
--- a/fs_mgr/libfiemap_writer/utility.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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 "utility.h"
-
-#include <stdint.h>
-#include <sys/vfs.h>
-#include <unistd.h>
-
-#include <android-base/logging.h>
-#include <libfiemap_writer/fiemap_writer.h>
-
-namespace android {
-namespace fiemap_writer {
-
-uint64_t DetermineMaximumFileSize(const std::string& file_path) {
-    // Create the smallest file possible (one block).
-    auto writer = FiemapWriter::Open(file_path, 1);
-    if (!writer) {
-        return 0;
-    }
-
-    uint64_t result = 0;
-    switch (writer->fs_type()) {
-        case EXT4_SUPER_MAGIC:
-            // The minimum is 16GiB, so just report that. If we wanted we could parse the
-            // superblock and figure out if 64-bit support is enabled.
-            result = 17179869184ULL;
-            break;
-        case F2FS_SUPER_MAGIC:
-            // Formula is from https://www.kernel.org/doc/Documentation/filesystems/f2fs.txt
-            // 4KB * (923 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
-            result = 4329690886144ULL;
-            break;
-        case MSDOS_SUPER_MAGIC:
-            // 4GB-1, which we want aligned to the block size.
-            result = 4294967295;
-            result -= (result % writer->block_size());
-            break;
-        default:
-            LOG(ERROR) << "Unknown file system type: " << writer->fs_type();
-            break;
-    }
-
-    // Close and delete the temporary file.
-    writer = nullptr;
-    unlink(file_path.c_str());
-
-    return result;
-}
-
-}  // namespace fiemap_writer
-}  // namespace android
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
index a3c76ab..bf51fe7 100644
--- a/fs_mgr/libfs_avb/Android.bp
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -37,11 +37,9 @@
         "libfstab",
     ],
     shared_libs: [
+        "libbase",
         "libcrypto",
     ],
-    header_libs: [
-        "libbase_headers",
-    ],
     target: {
         darwin: {
             enabled: false,
@@ -61,6 +59,7 @@
         "libavb",
         "libavb_host_sysdeps",
         "libdm",
+        "libext2_uuid",
         "libfs_avb",
         "libfstab",
         "libgtest_host",
@@ -122,6 +121,7 @@
 cc_test {
     name: "libfs_avb_device_test",
     test_suites: ["device-tests"],
+    require_root: true,
     static_libs: [
         "libavb",
         "libdm",
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
index d9650f3..4505382 100644
--- a/fs_mgr/libfs_avb/avb_util.cpp
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -104,31 +104,23 @@
     }
     table.set_readonly(true);
 
+    std::chrono::milliseconds timeout = {};
+    if (wait_for_verity_dev) timeout = 1s;
+
+    std::string dev_path;
     const std::string mount_point(Basename(fstab_entry->mount_point));
     const std::string device_name(GetVerityDeviceName(*fstab_entry));
     android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
-    if (!dm.CreateDevice(device_name, table)) {
+    if (!dm.CreateDevice(device_name, table, &dev_path, timeout)) {
         LERROR << "Couldn't create verity device!";
         return false;
     }
 
-    std::string dev_path;
-    if (!dm.GetDmDevicePathByName(device_name, &dev_path)) {
-        LERROR << "Couldn't get verity device path!";
-        return false;
-    }
-
     // Marks the underlying block device as read-only.
     SetBlockDeviceReadOnly(fstab_entry->blk_device);
 
     // Updates fstab_rec->blk_device to verity device name.
     fstab_entry->blk_device = dev_path;
-
-    // Makes sure we've set everything up properly.
-    if (wait_for_verity_dev && !WaitForFile(dev_path, 1s)) {
-        return false;
-    }
-
     return true;
 }
 
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index c4d7511..8770a6b 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -22,6 +22,7 @@
 #include <sys/ioctl.h>
 #include <sys/types.h>
 
+#include <algorithm>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -308,7 +309,18 @@
             return nullptr;
     }
 
-    if (!ValidatePublicKeyBlob(public_key_data, Split(fstab_entry.avb_keys, ":"))) {
+    // fstab_entry.avb_keys might be either a directory containing multiple keys,
+    // or a string indicating multiple keys separated by ':'.
+    std::vector<std::string> allowed_avb_keys;
+    auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys);
+    if (list_avb_keys_in_dir) {
+        std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end());
+        allowed_avb_keys = *list_avb_keys_in_dir;
+    } else {
+        allowed_avb_keys = Split(fstab_entry.avb_keys, ":");
+    }
+
+    if (!ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) {
         avb_handle->status_ = AvbHandleStatus::kVerificationError;
         LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point;
         if (!allow_verification_error) {
diff --git a/fs_mgr/libfs_avb/tests/avb_util_test.cpp b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
index 0d342d3..784eb9c 100644
--- a/fs_mgr/libfs_avb/tests/avb_util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/avb_util_test.cpp
@@ -101,10 +101,10 @@
 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",
+            .blk_device = "/dev/block/dm-1",  // a dm-linear device (logical)
+            .logical_partition_name = "system",
+            .mount_point = "/system",
+            .fs_type = "ext4",
     };
 
     // Logical partitions.
diff --git a/fs_mgr/libfs_avb/tests/util_test.cpp b/fs_mgr/libfs_avb/tests/util_test.cpp
index 12b5acb..e64282b 100644
--- a/fs_mgr/libfs_avb/tests/util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/util_test.cpp
@@ -16,10 +16,12 @@
 
 #include <unistd.h>
 
+#include <algorithm>
 #include <future>
 #include <string>
 #include <thread>
 
+#include <android-base/strings.h>
 #include <base/files/file_util.h>
 
 #include "fs_avb_test_util.h"
@@ -29,6 +31,7 @@
 using android::fs_mgr::BytesToHex;
 using android::fs_mgr::FileWaitMode;
 using android::fs_mgr::HexToBytes;
+using android::fs_mgr::ListFiles;
 using android::fs_mgr::NibbleValue;
 using android::fs_mgr::WaitForFile;
 
@@ -210,4 +213,102 @@
     ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
 }
 
+TEST(BasicUtilTest, ListFiles) {
+    // Gets system tmp dir.
+    base::FilePath tmp_dir;
+    ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+    // Creates a test dir for ListFiles testing.
+    base::FilePath test_dir;
+    ASSERT_TRUE(base::CreateTemporaryDirInDir(tmp_dir, "list-file-tests.", &test_dir));
+
+    // Generates dummy files to list.
+    base::FilePath file_path_1 = test_dir.Append("1.txt");
+    ASSERT_TRUE(base::WriteFile(file_path_1, "1", 1));
+    base::FilePath file_path_2 = test_dir.Append("2.txt");
+    ASSERT_TRUE(base::WriteFile(file_path_2, "22", 2));
+    base::FilePath file_path_3 = test_dir.Append("3.txt");
+    ASSERT_TRUE(base::WriteFile(file_path_3, "333", 3));
+
+    // List files for comparison.
+    auto result = ListFiles(test_dir.value());
+    ASSERT_TRUE(result);
+    ASSERT_TRUE(result.has_value());
+    auto files = result.value();
+    EXPECT_EQ(3UL, files.size());
+    // Sort them offline for comparison.
+    std::sort(files.begin(), files.end());
+    EXPECT_EQ(file_path_1.value(), files[0]);
+    EXPECT_EQ(file_path_2.value(), files[1]);
+    EXPECT_EQ(file_path_3.value(), files[2]);
+
+    ASSERT_TRUE(base::DeleteFile(test_dir, true /* resursive */));
+}
+
+TEST(BasicUtilTest, ListFilesShouldDiscardSymlink) {
+    // Gets system tmp dir.
+    base::FilePath tmp_dir;
+    ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+    // Creates a test dir for ListFiles testing.
+    base::FilePath test_dir;
+    ASSERT_TRUE(base::CreateTemporaryDirInDir(tmp_dir, "list-file-tests.", &test_dir));
+
+    // Generates dummy files to list.
+    base::FilePath file_path_1 = test_dir.Append("1.txt");
+    ASSERT_TRUE(base::WriteFile(file_path_1, "1", 1));
+    base::FilePath file_path_2 = test_dir.Append("2.txt");
+    ASSERT_TRUE(base::WriteFile(file_path_2, "22", 2));
+    // Creates a symlink and checks it won't be returned by ListFiles.
+    base::FilePath file_path_3 = test_dir.Append("3.txt");
+    base::FilePath non_existent_target = test_dir.Append("non_existent_target.txt");
+    ASSERT_TRUE(base::CreateSymbolicLink(non_existent_target, file_path_3));
+
+    // List files for comparison.
+    auto result = ListFiles(test_dir.value());
+    ASSERT_TRUE(result);
+    ASSERT_TRUE(result.has_value());
+    auto files = result.value();
+    EXPECT_EQ(2UL, files.size());  // Should not include the symlink file.
+    // Sort them offline for comparison.
+    std::sort(files.begin(), files.end());
+    EXPECT_EQ(file_path_1.value(), files[0]);
+    EXPECT_EQ(file_path_2.value(), files[1]);
+
+    ASSERT_TRUE(base::DeleteFile(test_dir, true /* resursive */));
+}
+
+TEST(BasicUtilTest, ListFilesOpenDirFailure) {
+    // Gets system tmp dir.
+    base::FilePath tmp_dir;
+    ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+    // Generates dummy files to list.
+    base::FilePath no_such_dir = tmp_dir.Append("not_such_dir");
+
+    auto fail = ListFiles(no_such_dir.value());
+    ASSERT_FALSE(fail);
+    EXPECT_EQ(ENOENT, fail.error().code());
+    EXPECT_TRUE(android::base::StartsWith(fail.error().message(), "Failed to opendir: "));
+}
+
+TEST(BasicUtilTest, ListFilesEmptyDir) {
+    // Gets system tmp dir.
+    base::FilePath tmp_dir;
+    ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+    // Creates a test dir for ListFiles testing.
+    base::FilePath test_dir;
+    ASSERT_TRUE(base::CreateTemporaryDirInDir(tmp_dir, "list-file-tests.", &test_dir));
+
+    // List files without sorting.
+    auto result = ListFiles(test_dir.value());
+    ASSERT_TRUE(result);
+    ASSERT_TRUE(result.has_value());
+    auto files = result.value();
+    EXPECT_EQ(0UL, files.size());
+
+    ASSERT_TRUE(base::DeleteFile(test_dir, true /* resursive */));
+}
+
 }  // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/util.cpp b/fs_mgr/libfs_avb/util.cpp
index d214b5b..7783d04 100644
--- a/fs_mgr/libfs_avb/util.cpp
+++ b/fs_mgr/libfs_avb/util.cpp
@@ -16,10 +16,13 @@
 
 #include "util.h"
 
+#include <dirent.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 
 #include <thread>
 
+#include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <linux/fs.h>
 
@@ -122,5 +125,23 @@
     return ioctl(fd, BLKROSET, &ON) == 0;
 }
 
+Result<std::vector<std::string>> ListFiles(const std::string& dir) {
+    struct dirent* de;
+    std::vector<std::string> files;
+
+    std::unique_ptr<DIR, int (*)(DIR*)> dirp(opendir(dir.c_str()), closedir);
+    if (!dirp) {
+        return ErrnoError() << "Failed to opendir: " << dir;
+    }
+
+    while ((de = readdir(dirp.get()))) {
+        if (de->d_type != DT_REG) continue;
+        std::string full_path = android::base::StringPrintf("%s/%s", dir.c_str(), de->d_name);
+        files.emplace_back(std::move(full_path));
+    }
+
+    return files;
+}
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/libfs_avb/util.h b/fs_mgr/libfs_avb/util.h
index 7763da5..427ab7c 100644
--- a/fs_mgr/libfs_avb/util.h
+++ b/fs_mgr/libfs_avb/util.h
@@ -18,6 +18,7 @@
 
 #include <chrono>
 #include <string>
+#include <vector>
 
 #ifdef HOST_TEST
 #include <base/logging.h>
@@ -25,6 +26,11 @@
 #include <android-base/logging.h>
 #endif
 
+#include <android-base/result.h>
+
+using android::base::ErrnoError;
+using android::base::Result;
+
 #define FS_AVB_TAG "[libfs_avb]"
 
 // Logs a message to kernel
@@ -60,5 +66,8 @@
 
 bool SetBlockDeviceReadOnly(const std::string& blockdev);
 
+// Returns a list of file under the dir, no order is guaranteed.
+Result<std::vector<std::string>> ListFiles(const std::string& dir);
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index b504161..ea0fca8 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -17,7 +17,6 @@
 liblp_lib_deps = [
     "libbase",
     "liblog",
-    "libcrypto",
     "libcrypto_utils",
     "libsparse",
     "libext4_utils",
@@ -36,11 +35,14 @@
         "builder.cpp",
         "images.cpp",
         "partition_opener.cpp",
+        "property_fetcher.cpp",
         "reader.cpp",
         "utility.cpp",
         "writer.cpp",
     ],
-    shared_libs: liblp_lib_deps,
+    shared_libs: [
+        "libcrypto",
+    ] + liblp_lib_deps,
     target: {
         windows: {
             enabled: true,
@@ -54,29 +56,55 @@
     export_include_dirs: ["include"],
 }
 
-cc_test {
-    name: "liblp_test_static",
+filegroup {
+    name: "liblp_test_srcs",
+    srcs: [
+        "builder_test.cpp",
+        "device_test.cpp",
+        "io_test.cpp",
+        "test_partition_opener.cpp",
+        "utility_test.cpp",
+    ],
+}
+
+cc_defaults {
+    name: "liblp_test_defaults",
     defaults: ["fs_mgr_defaults"],
     cppflags: [
         "-Wno-unused-parameter",
     ],
     static_libs: [
+        "libcutils",
         "libgmock",
         "libfs_mgr",
         "liblp",
+        "libcrypto_static",
     ] + liblp_lib_deps,
-    stl: "libc++_static",
-    srcs: [
-        "builder_test.cpp",
-        "io_test.cpp",
-        "test_partition_opener.cpp",
-        "utility_test.cpp",
+    header_libs: [
+        "libstorage_literals_headers",
     ],
-    target: {
-        android: {
-            static_libs: [
-                "libcutils",
-            ],
-        },
-    },
+    stl: "libc++_static",
+    srcs: [":liblp_test_srcs"],
 }
+
+cc_test {
+    name: "liblp_test",
+    defaults: ["liblp_test_defaults"],
+    test_config: "liblp_test.xml",
+    test_suites: ["device-tests"],
+}
+
+cc_test {
+    name: "vts_core_liblp_test",
+    defaults: ["liblp_test_defaults"],
+    test_suites: ["vts-core"],
+    auto_gen_config: true,
+    test_min_api_level: 29,
+    require_root: true,
+}
+
+cc_test {
+    name: "vts_kernel_liblp_test",
+    defaults: ["liblp_test_defaults"],
+}
+
diff --git a/fs_mgr/liblp/AndroidTest.xml b/fs_mgr/liblp/AndroidTest.xml
index fe1002c..2eb0ad1 100644
--- a/fs_mgr/liblp/AndroidTest.xml
+++ b/fs_mgr/liblp/AndroidTest.xml
@@ -21,8 +21,8 @@
     </target_preparer>
     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
       <option name="test-module-name" value="VtsKernelLiblpTest"/>
-        <option name="binary-test-source" value="_32bit::DATA/nativetest/liblp_test_static/liblp_test_static" />
-        <option name="binary-test-source" value="_64bit::DATA/nativetest64/liblp_test_static/liblp_test_static" />
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_kernel_liblp_test/vts_kernel_liblp_test" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_kernel_liblp_test/vts_kernel_liblp_test" />
         <option name="binary-test-type" value="gtest"/>
         <option name="test-timeout" value="1m"/>
         <option name="precondition-first-api-level" value="29" />
diff --git a/fs_mgr/liblp/TEST_MAPPING b/fs_mgr/liblp/TEST_MAPPING
new file mode 100644
index 0000000..04bcbda
--- /dev/null
+++ b/fs_mgr/liblp/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "liblp_test"
+    }
+  ]
+}
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 27222af..d496466 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -20,21 +20,16 @@
 
 #include <algorithm>
 
-#include <android-base/properties.h>
 #include <android-base/unique_fd.h>
 
 #include "liblp/liblp.h"
+#include "liblp/property_fetcher.h"
 #include "reader.h"
 #include "utility.h"
 
 namespace android {
 namespace fs_mgr {
 
-bool MetadataBuilder::sABOverrideSet;
-bool MetadataBuilder::sABOverrideValue;
-
-static const std::string kDefaultGroup = "default";
-
 bool LinearExtent::AddTo(LpMetadata* out) const {
     if (device_index_ >= out->block_devices.size()) {
         LERROR << "Extent references unknown block device.";
@@ -45,12 +40,16 @@
     return true;
 }
 
+Interval LinearExtent::AsInterval() const {
+    return Interval(device_index(), physical_sector(), end_sector());
+}
+
 bool ZeroExtent::AddTo(LpMetadata* out) const {
     out->extents.emplace_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_ZERO, 0, 0});
     return true;
 }
 
-Partition::Partition(const std::string& name, const std::string& group_name, uint32_t attributes)
+Partition::Partition(std::string_view name, std::string_view group_name, uint32_t attributes)
     : name_(name), group_name_(group_name), attributes_(attributes), size_(0) {}
 
 void Partition::AddExtent(std::unique_ptr<Extent>&& extent) {
@@ -101,6 +100,20 @@
     DCHECK(size_ == aligned_size);
 }
 
+Partition Partition::GetBeginningExtents(uint64_t aligned_size) const {
+    Partition p(name_, group_name_, attributes_);
+    for (const auto& extent : extents_) {
+        auto le = extent->AsLinearExtent();
+        if (le) {
+            p.AddExtent(std::make_unique<LinearExtent>(*le));
+        } else {
+            p.AddExtent(std::make_unique<ZeroExtent>(extent->num_sectors()));
+        }
+    }
+    p.ShrinkTo(aligned_size);
+    return p;
+}
+
 uint64_t Partition::BytesOnDisk() const {
     uint64_t sectors = 0;
     for (const auto& extent : extents_) {
@@ -145,7 +158,7 @@
     }
     if (opener) {
         for (size_t i = 0; i < builder->block_devices_.size(); i++) {
-            std::string partition_name = GetBlockDevicePartitionName(builder->block_devices_[i]);
+            std::string partition_name = builder->GetBlockDevicePartitionName(i);
             BlockDeviceInfo device_info;
             if (opener->GetInfo(partition_name, &device_info)) {
                 builder->UpdateBlockDeviceInfo(i, device_info);
@@ -158,21 +171,42 @@
 std::unique_ptr<MetadataBuilder> MetadataBuilder::NewForUpdate(const IPartitionOpener& opener,
                                                                const std::string& source_partition,
                                                                uint32_t source_slot_number,
-                                                               uint32_t target_slot_number) {
+                                                               uint32_t target_slot_number,
+                                                               bool always_keep_source_slot) {
     auto metadata = ReadMetadata(opener, source_partition, source_slot_number);
     if (!metadata) {
         return nullptr;
     }
 
-    // On non-retrofit devices there is only one location for metadata: the
-    // super partition. update_engine will remove and resize partitions as
-    // needed. On the other hand, for retrofit devices, we'll need to
-    // translate block device and group names to update their slot suffixes.
+    // On retrofit DAP devices, modify the metadata so that it is suitable for being written
+    // to the target slot later. We detect retrofit DAP devices by checking the super partition
+    // name and system properties.
+    // See comments for UpdateMetadataForOtherSuper.
     auto super_device = GetMetadataSuperBlockDevice(*metadata.get());
-    if (GetBlockDevicePartitionName(*super_device) == "super") {
-        return New(*metadata.get(), &opener);
+    if (android::fs_mgr::GetBlockDevicePartitionName(*super_device) != "super" &&
+        IsRetrofitDynamicPartitionsDevice()) {
+        if (!UpdateMetadataForOtherSuper(metadata.get(), source_slot_number, target_slot_number)) {
+            return nullptr;
+        }
     }
 
+    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false) &&
+        !always_keep_source_slot) {
+        if (!UpdateMetadataForInPlaceSnapshot(metadata.get(), source_slot_number,
+                                              target_slot_number)) {
+            return nullptr;
+        }
+    }
+
+    return New(*metadata.get(), &opener);
+}
+
+// For retrofit DAP devices, there are (conceptually) two super partitions. We'll need to translate
+// block device and group names to update their slot suffixes.
+// (On the other hand, On non-retrofit DAP devices there is only one location for metadata: the
+// super partition. update_engine will remove and resize partitions as needed.)
+bool MetadataBuilder::UpdateMetadataForOtherSuper(LpMetadata* metadata, uint32_t source_slot_number,
+                                                  uint32_t target_slot_number) {
     // Clear partitions and extents, since they have no meaning on the target
     // slot. We also clear groups since they are re-added during OTA.
     metadata->partitions.clear();
@@ -185,14 +219,15 @@
     // Translate block devices.
     auto source_block_devices = std::move(metadata->block_devices);
     for (const auto& source_block_device : source_block_devices) {
-        std::string partition_name = GetBlockDevicePartitionName(source_block_device);
+        std::string partition_name =
+                android::fs_mgr::GetBlockDevicePartitionName(source_block_device);
         std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
         if (slot_suffix.empty() || slot_suffix != source_slot_suffix) {
             // This should never happen. It means that the source metadata
             // refers to a target or unknown block device.
             LERROR << "Invalid block device for slot " << source_slot_suffix << ": "
                    << partition_name;
-            return nullptr;
+            return false;
         }
         std::string new_name =
                 partition_name.substr(0, partition_name.size() - slot_suffix.size()) +
@@ -201,20 +236,15 @@
         auto new_device = source_block_device;
         if (!UpdateBlockDevicePartitionName(&new_device, new_name)) {
             LERROR << "Partition name too long: " << new_name;
-            return nullptr;
+            return false;
         }
         metadata->block_devices.emplace_back(new_device);
     }
 
-    return New(*metadata.get(), &opener);
+    return true;
 }
 
-void MetadataBuilder::OverrideABForTesting(bool ab_device) {
-    sABOverrideSet = true;
-    sABOverrideValue = ab_device;
-}
-
-MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false), ignore_slot_suffixing_(false) {
+MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false) {
     memset(&geometry_, 0, sizeof(geometry_));
     geometry_.magic = LP_METADATA_GEOMETRY_MAGIC;
     geometry_.struct_size = sizeof(geometry_);
@@ -222,8 +252,8 @@
     memset(&header_, 0, sizeof(header_));
     header_.magic = LP_METADATA_HEADER_MAGIC;
     header_.major_version = LP_METADATA_MAJOR_VERSION;
-    header_.minor_version = LP_METADATA_MINOR_VERSION;
-    header_.header_size = sizeof(header_);
+    header_.minor_version = LP_METADATA_MINOR_VERSION_MIN;
+    header_.header_size = sizeof(LpMetadataHeaderV1_0);
     header_.partitions.entry_size = sizeof(LpMetadataPartition);
     header_.extents.entry_size = sizeof(LpMetadataExtent);
     header_.groups.entry_size = sizeof(LpMetadataPartitionGroup);
@@ -234,6 +264,12 @@
     geometry_ = metadata.geometry;
     block_devices_ = metadata.block_devices;
 
+    // Bump the version as necessary to copy any newer fields.
+    if (metadata.header.minor_version >= LP_METADATA_VERSION_FOR_EXPANDED_HEADER) {
+        RequireExpandedMetadataHeader();
+        header_.flags = metadata.header.flags;
+    }
+
     for (const auto& group : metadata.groups) {
         std::string group_name = GetPartitionGroupName(group);
         if (!AddGroup(group_name, group.maximum_size)) {
@@ -373,7 +409,7 @@
             block_devices_.emplace_back(out);
         }
     }
-    if (GetBlockDevicePartitionName(block_devices_[0]) != super_partition) {
+    if (GetBlockDevicePartitionName(0) != super_partition) {
         LERROR << "No super partition was specified.";
         return false;
     }
@@ -410,13 +446,13 @@
     geometry_.metadata_slot_count = metadata_slot_count;
     geometry_.logical_block_size = logical_block_size;
 
-    if (!AddGroup(kDefaultGroup, 0)) {
+    if (!AddGroup(std::string(kDefaultGroup), 0)) {
         return false;
     }
     return true;
 }
 
-bool MetadataBuilder::AddGroup(const std::string& group_name, uint64_t maximum_size) {
+bool MetadataBuilder::AddGroup(std::string_view group_name, uint64_t maximum_size) {
     if (FindGroup(group_name)) {
         LERROR << "Group already exists: " << group_name;
         return false;
@@ -429,7 +465,7 @@
     return AddPartition(name, kDefaultGroup, attributes);
 }
 
-Partition* MetadataBuilder::AddPartition(const std::string& name, const std::string& group_name,
+Partition* MetadataBuilder::AddPartition(std::string_view name, std::string_view group_name,
                                          uint32_t attributes) {
     if (name.empty()) {
         LERROR << "Partition must have a non-empty name.";
@@ -443,16 +479,11 @@
         LERROR << "Could not find partition group: " << group_name;
         return nullptr;
     }
-    if (IsABDevice() && !auto_slot_suffixing_ && name != "scratch" && !ignore_slot_suffixing_ &&
-        GetPartitionSlotSuffix(name).empty()) {
-        LERROR << "Unsuffixed partition not allowed on A/B device: " << name;
-        return nullptr;
-    }
     partitions_.push_back(std::make_unique<Partition>(name, group_name, attributes));
     return partitions_.back().get();
 }
 
-Partition* MetadataBuilder::FindPartition(const std::string& name) {
+Partition* MetadataBuilder::FindPartition(std::string_view name) {
     for (const auto& partition : partitions_) {
         if (partition->name() == name) {
             return partition.get();
@@ -461,7 +492,7 @@
     return nullptr;
 }
 
-PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
+PartitionGroup* MetadataBuilder::FindGroup(std::string_view group_name) {
     for (const auto& group : groups_) {
         if (group->name() == group_name) {
             return group.get();
@@ -481,7 +512,7 @@
     return total;
 }
 
-void MetadataBuilder::RemovePartition(const std::string& name) {
+void MetadataBuilder::RemovePartition(std::string_view name) {
     for (auto iter = partitions_.begin(); iter != partitions_.end(); iter++) {
         if ((*iter)->name() == name) {
             partitions_.erase(iter);
@@ -574,18 +605,48 @@
     return true;
 }
 
-bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) {
+Interval Interval::Intersect(const Interval& a, const Interval& b) {
+    Interval ret = a;
+    if (a.device_index != b.device_index) {
+        ret.start = ret.end = a.start;  // set length to 0 to indicate no intersection.
+        return ret;
+    }
+    ret.start = std::max(a.start, b.start);
+    ret.end = std::max(ret.start, std::min(a.end, b.end));
+    return ret;
+}
+
+std::vector<Interval> Interval::Intersect(const std::vector<Interval>& a,
+                                          const std::vector<Interval>& b) {
+    std::vector<Interval> ret;
+    for (const Interval& a_interval : a) {
+        for (const Interval& b_interval : b) {
+            auto intersect = Intersect(a_interval, b_interval);
+            if (intersect.length() > 0) ret.emplace_back(std::move(intersect));
+        }
+    }
+    return ret;
+}
+
+std::unique_ptr<Extent> Interval::AsExtent() const {
+    return std::make_unique<LinearExtent>(length(), device_index, start);
+}
+
+bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size,
+                                    const std::vector<Interval>& free_region_hint) {
     uint64_t space_needed = aligned_size - partition->size();
     uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE;
     DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed);
 
     std::vector<Interval> free_regions = GetFreeRegions();
+    if (!free_region_hint.empty())
+        free_regions = Interval::Intersect(free_regions, free_region_hint);
 
     const uint64_t sectors_per_block = geometry_.logical_block_size / LP_SECTOR_SIZE;
     CHECK_NE(sectors_per_block, 0);
     CHECK(sectors_needed % sectors_per_block == 0);
 
-    if (IsABDevice() && !IsRetrofitDevice() && GetPartitionSlotSuffix(partition->name()) == "_b") {
+    if (IsABDevice() && ShouldHalveSuper() && GetPartitionSlotSuffix(partition->name()) == "_b") {
         // Allocate "a" partitions top-down and "b" partitions bottom-up, to
         // minimize fragmentation during OTA.
         free_regions = PrioritizeSecondHalfOfSuper(free_regions);
@@ -645,7 +706,7 @@
     return true;
 }
 
-std::vector<MetadataBuilder::Interval> MetadataBuilder::PrioritizeSecondHalfOfSuper(
+std::vector<Interval> MetadataBuilder::PrioritizeSecondHalfOfSuper(
         const std::vector<Interval>& free_list) {
     const auto& super = block_devices_[0];
     uint64_t first_sector = super.first_logical_sector;
@@ -791,6 +852,11 @@
             return nullptr;
         }
 
+        if (partition->attributes() & LP_PARTITION_ATTRIBUTE_MASK_V1) {
+            static const uint16_t kMinVersion = LP_METADATA_VERSION_FOR_UPDATED_ATTR;
+            metadata->header.minor_version = std::max(metadata->header.minor_version, kMinVersion);
+        }
+
         strncpy(part.name, partition->name().c_str(), sizeof(part.name));
         part.first_extent_index = static_cast<uint32_t>(metadata->extents.size());
         part.num_extents = static_cast<uint32_t>(partition->extents().size());
@@ -823,6 +889,14 @@
     return metadata;
 }
 
+void MetadataBuilder::RequireExpandedMetadataHeader() {
+    if (header_.minor_version >= LP_METADATA_VERSION_FOR_EXPANDED_HEADER) {
+        return;
+    }
+    header_.minor_version = LP_METADATA_VERSION_FOR_EXPANDED_HEADER;
+    header_.header_size = sizeof(LpMetadataHeaderV1_2);
+}
+
 uint64_t MetadataBuilder::AllocatableSpace() const {
     uint64_t total_size = 0;
     for (const auto& block_device : block_devices_) {
@@ -851,7 +925,7 @@
 bool MetadataBuilder::FindBlockDeviceByName(const std::string& partition_name,
                                             uint32_t* index) const {
     for (size_t i = 0; i < block_devices_.size(); i++) {
-        if (GetBlockDevicePartitionName(block_devices_[i]) == partition_name) {
+        if (GetBlockDevicePartitionName(i) == partition_name) {
             *index = i;
             return true;
         }
@@ -916,7 +990,8 @@
     return true;
 }
 
-bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
+bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size,
+                                      const std::vector<Interval>& free_region_hint) {
     // Align the space needed up to the nearest sector.
     uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size);
     uint64_t old_size = partition->size();
@@ -926,7 +1001,7 @@
     }
 
     if (aligned_size > old_size) {
-        if (!GrowPartition(partition, aligned_size)) {
+        if (!GrowPartition(partition, aligned_size, free_region_hint)) {
             return false;
         }
     } else if (aligned_size < partition->size()) {
@@ -948,7 +1023,7 @@
     return names;
 }
 
-void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) {
+void MetadataBuilder::RemoveGroupAndPartitions(std::string_view group_name) {
     if (group_name == kDefaultGroup) {
         // Cannot remove the default group.
         return;
@@ -976,7 +1051,8 @@
     // Note: we don't compare alignment, since it's a performance thing and
     // won't affect whether old extents continue to work.
     return first.first_logical_sector == second.first_logical_sector && first.size == second.size &&
-           GetBlockDevicePartitionName(first) == GetBlockDevicePartitionName(second);
+           android::fs_mgr::GetBlockDevicePartitionName(first) ==
+                   android::fs_mgr::GetBlockDevicePartitionName(second);
 }
 
 bool MetadataBuilder::ImportPartitions(const LpMetadata& metadata,
@@ -1049,19 +1125,23 @@
     auto_slot_suffixing_ = true;
 }
 
-void MetadataBuilder::IgnoreSlotSuffixing() {
-    ignore_slot_suffixing_ = true;
+void MetadataBuilder::SetVirtualABDeviceFlag() {
+    RequireExpandedMetadataHeader();
+    header_.flags |= LP_HEADER_FLAG_VIRTUAL_AB_DEVICE;
 }
 
-bool MetadataBuilder::IsABDevice() const {
-    if (sABOverrideSet) {
-        return sABOverrideValue;
-    }
-    return android::base::GetBoolProperty("ro.build.ab_update", false);
+bool MetadataBuilder::IsABDevice() {
+    return !IPropertyFetcher::GetInstance()->GetProperty("ro.boot.slot_suffix", "").empty();
 }
 
-bool MetadataBuilder::IsRetrofitDevice() const {
-    return GetBlockDevicePartitionName(block_devices_[0]) != LP_METADATA_DEFAULT_PARTITION_NAME;
+bool MetadataBuilder::IsRetrofitDynamicPartitionsDevice() {
+    return IPropertyFetcher::GetInstance()->GetBoolProperty("ro.boot.dynamic_partitions_retrofit",
+                                                            false);
+}
+
+bool MetadataBuilder::ShouldHalveSuper() const {
+    return GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
+           !IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false);
 }
 
 bool MetadataBuilder::AddLinearExtent(Partition* partition, const std::string& block_device,
@@ -1077,7 +1157,7 @@
     return true;
 }
 
-std::vector<Partition*> MetadataBuilder::ListPartitionsInGroup(const std::string& group_name) {
+std::vector<Partition*> MetadataBuilder::ListPartitionsInGroup(std::string_view group_name) {
     std::vector<Partition*> partitions;
     for (const auto& partition : partitions_) {
         if (partition->group_name() == group_name) {
@@ -1087,7 +1167,7 @@
     return partitions;
 }
 
-bool MetadataBuilder::ChangePartitionGroup(Partition* partition, const std::string& group_name) {
+bool MetadataBuilder::ChangePartitionGroup(Partition* partition, std::string_view group_name) {
     if (!FindGroup(group_name)) {
         LERROR << "Partition cannot change to unknown group: " << group_name;
         return false;
@@ -1125,5 +1205,15 @@
     return true;
 }
 
+std::string MetadataBuilder::GetBlockDevicePartitionName(uint64_t index) const {
+    return index < block_devices_.size()
+                   ? android::fs_mgr::GetBlockDevicePartitionName(block_devices_[index])
+                   : "";
+}
+
+uint64_t MetadataBuilder::logical_block_size() const {
+    return geometry_.logical_block_size;
+}
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 46bfe92..ca8df61 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -14,34 +14,35 @@
  * limitations under the License.
  */
 
-#include <fs_mgr.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <liblp/builder.h>
+#include <storage_literals/storage_literals.h>
 
+#include "liblp_test.h"
 #include "utility.h"
 
 using namespace std;
+using namespace android::storage_literals;
 using namespace android::fs_mgr;
+using namespace android::fs_mgr::testing;
+using ::testing::_;
+using ::testing::AnyNumber;
 using ::testing::ElementsAre;
+using ::testing::NiceMock;
+using ::testing::Return;
 
 class Environment : public ::testing::Environment {
   public:
-    void SetUp() override { MetadataBuilder::OverrideABForTesting(false); }
+    void SetUp() override { ResetMockPropertyFetcher(); }
 };
 
 int main(int argc, char** argv) {
-    std::unique_ptr<Environment> env(new Environment);
-    ::testing::AddGlobalTestEnvironment(env.get());
     ::testing::InitGoogleTest(&argc, argv);
     return RUN_ALL_TESTS();
 }
 
-class BuilderTest : public ::testing::Test {
-  public:
-    void SetUp() override { MetadataBuilder::OverrideABForTesting(false); }
-    void TearDown() override { MetadataBuilder::OverrideABForTesting(false); }
-};
+class BuilderTest : public LiblpTest {};
 
 TEST_F(BuilderTest, BuildBasic) {
     unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
@@ -106,6 +107,13 @@
     EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
     EXPECT_EQ(extent->physical_sector(), 32);
 
+    auto exported = builder->Export();
+    ASSERT_NE(exported, nullptr);
+    ASSERT_EQ(FindPartition(*exported.get(), "not found"), nullptr);
+    auto entry = FindPartition(*exported.get(), "system");
+    ASSERT_NE(entry, nullptr);
+    ASSERT_EQ(GetPartitionSize(*exported.get(), *entry), 32768);
+
     // Test shrinking to 0.
     builder->ResizePartition(system, 0);
     EXPECT_EQ(system->size(), 0);
@@ -343,7 +351,8 @@
     const LpMetadataHeader& header = exported->header;
     EXPECT_EQ(header.magic, LP_METADATA_HEADER_MAGIC);
     EXPECT_EQ(header.major_version, LP_METADATA_MAJOR_VERSION);
-    EXPECT_EQ(header.minor_version, LP_METADATA_MINOR_VERSION);
+    EXPECT_EQ(header.minor_version, LP_METADATA_MINOR_VERSION_MIN);
+    EXPECT_EQ(header.header_size, sizeof(LpMetadataHeaderV1_0));
 
     ASSERT_EQ(exported->partitions.size(), 2);
     ASSERT_EQ(exported->extents.size(), 3);
@@ -441,23 +450,6 @@
     EXPECT_EQ(builder, nullptr);
 }
 
-TEST_F(BuilderTest, block_device_info) {
-    PartitionOpener opener;
-
-    BlockDeviceInfo device_info;
-    ASSERT_TRUE(opener.GetInfo(fs_mgr_get_super_partition_name(), &device_info));
-
-    // Sanity check that the device doesn't give us some weird inefficient
-    // alignment.
-    ASSERT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
-    ASSERT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0);
-    ASSERT_LE(device_info.alignment_offset, INT_MAX);
-    ASSERT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
-
-    // Having an alignment offset > alignment doesn't really make sense.
-    ASSERT_LT(device_info.alignment_offset, device_info.alignment);
-}
-
 TEST_F(BuilderTest, UpdateBlockDeviceInfo) {
     BlockDeviceInfo device_info("super", 1024 * 1024, 4096, 1024, 4096);
     unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
@@ -602,13 +594,6 @@
     ASSERT_NE(builder->Export(), nullptr);
 }
 
-constexpr unsigned long long operator"" _GiB(unsigned long long x) {  // NOLINT
-    return x << 30;
-}
-constexpr unsigned long long operator"" _MiB(unsigned long long x) {  // NOLINT
-    return x << 20;
-}
-
 TEST_F(BuilderTest, RemoveAndAddFirstPartition) {
     auto builder = MetadataBuilder::New(10_GiB, 65536, 2);
     ASSERT_NE(nullptr, builder);
@@ -765,21 +750,14 @@
     EXPECT_FALSE(builder->ImportPartitions(*exported.get(), {"system"}));
 }
 
-TEST_F(BuilderTest, UnsuffixedPartitions) {
-    MetadataBuilder::OverrideABForTesting(true);
-    unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
-    ASSERT_NE(builder, nullptr);
-
-    ASSERT_EQ(builder->AddPartition("system", 0), nullptr);
-    ASSERT_NE(builder->AddPartition("system_a", 0), nullptr);
-}
-
 TEST_F(BuilderTest, ABExtents) {
     BlockDeviceInfo device_info("super", 10_GiB, 768 * 1024, 0, 4096);
 
     // A and B slots should be allocated from separate halves of the partition,
     // to mitigate allocating too many extents. (b/120433288)
-    MetadataBuilder::OverrideABForTesting(true);
+    ON_CALL(*GetMockedPropertyFetcher(), GetProperty("ro.boot.slot_suffix", _))
+            .WillByDefault(Return("_a"));
+
     auto builder = MetadataBuilder::New(device_info, 65536, 2);
     ASSERT_NE(builder, nullptr);
     Partition* system_a = builder->AddPartition("system_a", 0);
@@ -905,3 +883,57 @@
     std::set<std::string> partitions_to_keep{"system_a", "vendor_a", "product_a"};
     ASSERT_TRUE(builder->ImportPartitions(*on_disk.get(), partitions_to_keep));
 }
+
+// Interval has operator< defined; it is not appropriate to re-define Interval::operator== that
+// compares device index.
+namespace android {
+namespace fs_mgr {
+bool operator==(const Interval& a, const Interval& b) {
+    return a.device_index == b.device_index && a.start == b.start && a.end == b.end;
+}
+}  // namespace fs_mgr
+}  // namespace android
+
+TEST_F(BuilderTest, Interval) {
+    EXPECT_EQ(0u, Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 100)).length());
+    EXPECT_EQ(Interval(0, 100, 150),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 150)));
+    EXPECT_EQ(Interval(0, 100, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 200)));
+    EXPECT_EQ(Interval(0, 100, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 250)));
+    EXPECT_EQ(Interval(0, 100, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 100, 200)));
+    EXPECT_EQ(Interval(0, 150, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 150, 250)));
+    EXPECT_EQ(0u, Interval::Intersect(Interval(0, 100, 200), Interval(0, 200, 250)).length());
+
+    auto v = Interval::Intersect(std::vector<Interval>{Interval(0, 0, 50), Interval(0, 100, 150)},
+                                 std::vector<Interval>{Interval(0, 25, 125)});
+    ASSERT_EQ(2, v.size());
+    EXPECT_EQ(Interval(0, 25, 50), v[0]);
+    EXPECT_EQ(Interval(0, 100, 125), v[1]);
+
+    EXPECT_EQ(0u, Interval::Intersect(std::vector<Interval>{Interval(0, 0, 50)},
+                                      std::vector<Interval>{Interval(0, 100, 150)})
+                          .size());
+}
+
+TEST_F(BuilderTest, ExpandedHeader) {
+    unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+    ASSERT_NE(builder, nullptr);
+
+    builder->RequireExpandedMetadataHeader();
+
+    unique_ptr<LpMetadata> exported = builder->Export();
+    ASSERT_NE(exported, nullptr);
+    EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2));
+
+    exported->header.flags = 0x5e5e5e5e;
+
+    builder = MetadataBuilder::New(*exported.get());
+    exported = builder->Export();
+    ASSERT_NE(exported, nullptr);
+    EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2));
+    EXPECT_EQ(exported->header.flags, 0x5e5e5e5e);
+}
diff --git a/fs_mgr/liblp/device_test.cpp b/fs_mgr/liblp/device_test.cpp
new file mode 100644
index 0000000..382d53d
--- /dev/null
+++ b/fs_mgr/liblp/device_test.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 <android-base/properties.h>
+#include <fs_mgr.h>
+#include <fstab/fstab.h>
+#include <gtest/gtest.h>
+#include <liblp/liblp.h>
+#include <liblp/metadata_format.h>
+#include <liblp/partition_opener.h>
+#include <liblp/property_fetcher.h>
+
+#include "liblp_test.h"
+
+using namespace android::fs_mgr;
+using namespace android::fs_mgr::testing;
+using ::testing::Return;
+
+// Compliance test on the actual device with dynamic partitions.
+class DeviceTest : public LiblpTest {
+  public:
+    void SetUp() override {
+        // Read real properties.
+        IPropertyFetcher::OverrideForTesting(std::make_unique<PropertyFetcher>());
+        if (!IPropertyFetcher::GetInstance()->GetBoolProperty("ro.boot.dynamic_partitions",
+                                                              false)) {
+            GTEST_SKIP() << "Device doesn't have dynamic partitions enabled, skipping";
+        }
+    }
+};
+
+TEST_F(DeviceTest, BlockDeviceInfo) {
+    PartitionOpener opener;
+    BlockDeviceInfo device_info;
+    ASSERT_TRUE(opener.GetInfo(fs_mgr_get_super_partition_name(), &device_info));
+
+    // Sanity check that the device doesn't give us some weird inefficient
+    // alignment.
+    EXPECT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
+    EXPECT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0);
+    EXPECT_LE(device_info.alignment_offset, INT_MAX);
+    EXPECT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
+
+    // Having an alignment offset > alignment doesn't really make sense.
+    EXPECT_LT(device_info.alignment_offset, device_info.alignment);
+}
+
+TEST_F(DeviceTest, ReadSuperPartitionCurrentSlot) {
+    auto slot_suffix = fs_mgr_get_slot_suffix();
+    auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
+    auto super_name = fs_mgr_get_super_partition_name(slot_number);
+    auto metadata = ReadMetadata(super_name, slot_number);
+    EXPECT_NE(metadata, nullptr);
+}
+
+TEST_F(DeviceTest, ReadSuperPartitionOtherSlot) {
+    auto other_slot_suffix = fs_mgr_get_other_slot_suffix();
+    if (other_slot_suffix.empty()) {
+        GTEST_SKIP() << "No other slot, skipping";
+    }
+    if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.boot.dynamic_partitions_retrofit",
+                                                         false)) {
+        GTEST_SKIP() << "Device with retrofit dynamic partition may not have metadata at other "
+                     << "slot, skipping";
+    }
+
+    auto other_slot_number = SlotNumberForSlotSuffix(other_slot_suffix);
+    auto other_super_name = fs_mgr_get_super_partition_name(other_slot_number);
+    auto other_metadata = ReadMetadata(other_super_name, other_slot_number);
+    EXPECT_NE(other_metadata, nullptr);
+}
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index db27022..e4d92ca 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -17,6 +17,7 @@
 #include "images.h"
 
 #include <limits.h>
+#include <sys/stat.h>
 
 #include <android-base/file.h>
 
@@ -27,12 +28,45 @@
 namespace android {
 namespace fs_mgr {
 
+using android::base::borrowed_fd;
 using android::base::unique_fd;
 
 #if defined(_WIN32)
 static const int O_NOFOLLOW = 0;
 #endif
 
+static bool IsEmptySuperImage(borrowed_fd fd) {
+    struct stat s;
+    if (fstat(fd.get(), &s) < 0) {
+        PERROR << __PRETTY_FUNCTION__ << " fstat failed";
+        return false;
+    }
+    if (s.st_size < LP_METADATA_GEOMETRY_SIZE) {
+        return false;
+    }
+
+    // Rewind back to the start, read the geometry struct.
+    LpMetadataGeometry geometry = {};
+    if (SeekFile64(fd.get(), 0, SEEK_SET) < 0) {
+        PERROR << __PRETTY_FUNCTION__ << " lseek failed";
+        return false;
+    }
+    if (!android::base::ReadFully(fd, &geometry, sizeof(geometry))) {
+        PERROR << __PRETTY_FUNCTION__ << " read failed";
+        return false;
+    }
+    return geometry.magic == LP_METADATA_GEOMETRY_MAGIC;
+}
+
+bool IsEmptySuperImage(const std::string& file) {
+    unique_fd fd = GetControlFileOrOpen(file, O_RDONLY | O_CLOEXEC);
+    if (fd < 0) {
+        PERROR << __PRETTY_FUNCTION__ << " open failed";
+        return false;
+    }
+    return IsEmptySuperImage(fd);
+}
+
 std::unique_ptr<LpMetadata> ReadFromImageFile(int fd) {
     std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(LP_METADATA_GEOMETRY_SIZE);
     if (SeekFile64(fd, 0, SEEK_SET) < 0) {
@@ -76,7 +110,7 @@
     return ReadFromImageFile(fd);
 }
 
-bool WriteToImageFile(int fd, const LpMetadata& input) {
+bool WriteToImageFile(borrowed_fd fd, const LpMetadata& input) {
     std::string geometry = SerializeGeometry(input.geometry);
     std::string metadata = SerializeMetadata(input);
 
@@ -89,8 +123,8 @@
     return true;
 }
 
-bool WriteToImageFile(const char* file, const LpMetadata& input) {
-    unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
+bool WriteToImageFile(const std::string& file, const LpMetadata& input) {
+    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
     if (fd < 0) {
         PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
         return false;
@@ -149,8 +183,8 @@
     return device_images_.size() == metadata_.block_devices.size();
 }
 
-bool ImageBuilder::Export(const char* file) {
-    unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
+bool ImageBuilder::Export(const std::string& file) {
+    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644));
     if (fd < 0) {
         PERROR << "open failed: " << file;
         return false;
@@ -438,7 +472,7 @@
     return temp_fds_.back().get();
 }
 
-bool WriteToImageFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
+bool WriteToImageFile(const std::string& file, const LpMetadata& metadata, uint32_t block_size,
                       const std::map<std::string, std::string>& images, bool sparsify) {
     ImageBuilder builder(metadata, block_size, images, sparsify);
     return builder.IsValid() && builder.Build() && builder.Export(file);
diff --git a/fs_mgr/liblp/images.h b/fs_mgr/liblp/images.h
index 75060f9..88e5882 100644
--- a/fs_mgr/liblp/images.h
+++ b/fs_mgr/liblp/images.h
@@ -29,8 +29,6 @@
 // Helper function to serialize geometry and metadata to a normal file, for
 // flashing or debugging.
 std::unique_ptr<LpMetadata> ReadFromImageFile(int fd);
-bool WriteToImageFile(const char* file, const LpMetadata& metadata);
-bool WriteToImageFile(int fd, const LpMetadata& metadata);
 
 // We use an object to build the image file since it requires that data
 // pointers be held alive until the sparse file is destroyed. It's easier
@@ -41,7 +39,7 @@
                  const std::map<std::string, std::string>& images, bool sparsify);
 
     bool Build();
-    bool Export(const char* file);
+    bool Export(const std::string& file);
     bool ExportFiles(const std::string& dir);
     bool IsValid() const;
 
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index c706f2a..f7738fb 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -24,6 +24,7 @@
 #include <memory>
 #include <optional>
 #include <set>
+#include <string_view>
 
 #include "liblp.h"
 #include "partition_opener.h"
@@ -32,10 +33,14 @@
 namespace fs_mgr {
 
 class LinearExtent;
+struct Interval;
 
 // By default, partitions are aligned on a 1MiB boundary.
-static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
-static const uint32_t kDefaultBlockSize = 4096;
+static constexpr uint32_t kDefaultPartitionAlignment = 1024 * 1024;
+static constexpr uint32_t kDefaultBlockSize = 4096;
+
+// Name of the default group in a metadata.
+static constexpr std::string_view kDefaultGroup = "default";
 
 // Abstraction around dm-targets that can be encoded into logical partition tables.
 class Extent {
@@ -70,6 +75,8 @@
         return sector >= physical_sector_ && sector < end_sector();
     }
 
+    Interval AsInterval() const;
+
   private:
     uint32_t device_index_;
     uint64_t physical_sector_;
@@ -87,7 +94,7 @@
     friend class MetadataBuilder;
 
   public:
-    explicit PartitionGroup(const std::string& name, uint64_t maximum_size)
+    explicit PartitionGroup(std::string_view name, uint64_t maximum_size)
         : name_(name), maximum_size_(maximum_size) {}
 
     const std::string& name() const { return name_; }
@@ -104,7 +111,7 @@
     friend class MetadataBuilder;
 
   public:
-    Partition(const std::string& name, const std::string& group_name, uint32_t attributes);
+    Partition(std::string_view name, std::string_view group_name, uint32_t attributes);
 
     // Add a raw extent.
     void AddExtent(std::unique_ptr<Extent>&& extent);
@@ -119,18 +126,55 @@
     const std::string& name() const { return name_; }
     const std::string& group_name() const { return group_name_; }
     uint32_t attributes() const { return attributes_; }
+    void set_attributes(uint32_t attributes) { attributes_ = attributes; }
     const std::vector<std::unique_ptr<Extent>>& extents() const { return extents_; }
     uint64_t size() const { return size_; }
 
+    // Return a copy of *this, but with extents that includes only the first
+    // |aligned_size| bytes. |aligned_size| should be aligned to
+    // logical_block_size() of the MetadataBuilder that this partition belongs
+    // to.
+    Partition GetBeginningExtents(uint64_t aligned_size) const;
+
   private:
     void ShrinkTo(uint64_t aligned_size);
-    void set_group_name(const std::string& group_name) { group_name_ = group_name; }
+    void set_group_name(std::string_view group_name) { group_name_ = group_name; }
 
     std::string name_;
     std::string group_name_;
     std::vector<std::unique_ptr<Extent>> extents_;
     uint32_t attributes_;
     uint64_t size_;
+    bool disabled_;
+};
+
+// An interval in the metadata. This is similar to a LinearExtent with one difference.
+// LinearExtent represents a "used" region in the metadata, while Interval can also represent
+// an "unused" region.
+struct Interval {
+    uint32_t device_index;
+    uint64_t start;
+    uint64_t end;
+
+    Interval(uint32_t device_index, uint64_t start, uint64_t end)
+        : device_index(device_index), start(start), end(end) {}
+    uint64_t length() const { return end - start; }
+
+    // Note: the device index is not included in sorting (intervals are
+    // sorted in per-device lists).
+    bool operator<(const Interval& other) const {
+        return (start == other.start) ? end < other.end : start < other.start;
+    }
+
+    std::unique_ptr<Extent> AsExtent() const;
+
+    // Intersect |a| with |b|.
+    // If no intersection, result has 0 length().
+    static Interval Intersect(const Interval& a, const Interval& b);
+
+    // Intersect two lists of intervals, and store result to |a|.
+    static std::vector<Interval> Intersect(const std::vector<Interval>& a,
+                                           const std::vector<Interval>& b);
 };
 
 class MetadataBuilder {
@@ -166,10 +210,13 @@
     // metadata may not have the target slot's devices listed yet, in which
     // case, it is automatically upgraded to include all available block
     // devices.
+    // If |always_keep_source_slot| is set, on a Virtual A/B device, source slot
+    // partitions are kept. This is useful when applying a downgrade package.
     static std::unique_ptr<MetadataBuilder> NewForUpdate(const IPartitionOpener& opener,
                                                          const std::string& source_partition,
                                                          uint32_t source_slot_number,
-                                                         uint32_t target_slot_number);
+                                                         uint32_t target_slot_number,
+                                                         bool always_keep_source_slot = false);
 
     // Import an existing table for modification. If the table is not valid, for
     // example it contains duplicate partition names, then nullptr is returned.
@@ -196,15 +243,12 @@
         return New(device_info, metadata_max_size, metadata_slot_count);
     }
 
-    // Used by the test harness to override whether the device is "A/B".
-    static void OverrideABForTesting(bool ab_device);
-
     // Define a new partition group. By default there is one group called
     // "default", with an unrestricted size. A non-zero size will restrict the
     // total space used by all partitions in the group.
     //
     // This can fail and return false if the group already exists.
-    bool AddGroup(const std::string& group_name, uint64_t maximum_size);
+    bool AddGroup(std::string_view group_name, uint64_t maximum_size);
 
     // Export metadata so it can be serialized to an image, to disk, or mounted
     // via device-mapper.
@@ -212,7 +256,7 @@
 
     // Add a partition, returning a handle so it can be sized as needed. If a
     // partition with the given name already exists, nullptr is returned.
-    Partition* AddPartition(const std::string& name, const std::string& group_name,
+    Partition* AddPartition(std::string_view name, std::string_view group_name,
                             uint32_t attributes);
 
     // Same as AddPartition above, but uses the default partition group which
@@ -220,13 +264,13 @@
     Partition* AddPartition(const std::string& name, uint32_t attributes);
 
     // Delete a partition by name if it exists.
-    void RemovePartition(const std::string& name);
+    void RemovePartition(std::string_view name);
 
     // Find a partition by name. If no partition is found, nullptr is returned.
-    Partition* FindPartition(const std::string& name);
+    Partition* FindPartition(std::string_view name);
 
     // Find a group by name. If no group is found, nullptr is returned.
-    PartitionGroup* FindGroup(const std::string& name);
+    PartitionGroup* FindGroup(std::string_view name);
 
     // Add a predetermined extent to a partition.
     bool AddLinearExtent(Partition* partition, const std::string& block_device,
@@ -242,16 +286,20 @@
     //
     // Note, this is an in-memory operation, and it does not alter the
     // underlying filesystem or contents of the partition on disk.
-    bool ResizePartition(Partition* partition, uint64_t requested_size);
+    //
+    // If |free_region_hint| is not empty, it will only try to allocate extents
+    // in regions within the list.
+    bool ResizePartition(Partition* partition, uint64_t requested_size,
+                         const std::vector<Interval>& free_region_hint = {});
 
     // Return the list of partitions belonging to a group.
-    std::vector<Partition*> ListPartitionsInGroup(const std::string& group_name);
+    std::vector<Partition*> ListPartitionsInGroup(std::string_view group_name);
 
     // Changes a partition's group. Size constraints will not be checked until
     // the metadata is exported, to avoid errors during potential group and
     // size shuffling operations. This will return false if the new group does
     // not exist.
-    bool ChangePartitionGroup(Partition* partition, const std::string& group_name);
+    bool ChangePartitionGroup(Partition* partition, std::string_view group_name);
 
     // Changes the size of a partition group. Size constraints will not be
     // checked until metadata is exported, to avoid errors during group
@@ -267,10 +315,12 @@
     std::vector<std::string> ListGroups() const;
 
     // Remove all partitions belonging to a group, then remove the group.
-    void RemoveGroupAndPartitions(const std::string& group_name);
+    void RemoveGroupAndPartitions(std::string_view group_name);
 
     // Set the LP_METADATA_AUTO_SLOT_SUFFIXING flag.
     void SetAutoSlotSuffixing();
+    // Set the LP_HEADER_FLAG_VIRTUAL_AB_DEVICE flag.
+    void SetVirtualABDeviceFlag();
 
     // If set, checks for slot suffixes will be ignored internally.
     void IgnoreSlotSuffixing();
@@ -278,6 +328,10 @@
     bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const;
     bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info);
 
+    // Require the expanded metadata header. This is exposed for testing, and
+    // is normally only called as needed by other methods.
+    void RequireExpandedMetadataHeader();
+
     // Attempt to preserve the named partitions from an older metadata. If this
     // is not possible (for example, the block device list has changed) then
     // false is returned.
@@ -286,6 +340,14 @@
     // Return true if a block device is found, else false.
     bool HasBlockDevice(const std::string& partition_name) const;
 
+    // Return the name of the block device at |index|.
+    std::string GetBlockDevicePartitionName(uint64_t index) const;
+
+    // Return the list of free regions not occupied by extents in the metadata.
+    std::vector<Interval> GetFreeRegions() const;
+
+    uint64_t logical_block_size() const;
+
   private:
     MetadataBuilder();
     MetadataBuilder(const MetadataBuilder&) = delete;
@@ -295,7 +357,8 @@
     bool Init(const std::vector<BlockDeviceInfo>& block_devices, const std::string& super_partition,
               uint32_t metadata_max_size, uint32_t metadata_slot_count);
     bool Init(const LpMetadata& metadata);
-    bool GrowPartition(Partition* partition, uint64_t aligned_size);
+    bool GrowPartition(Partition* partition, uint64_t aligned_size,
+                       const std::vector<Interval>& free_region_hint);
     void ShrinkPartition(Partition* partition, uint64_t aligned_size);
     uint64_t AlignSector(const LpMetadataBlockDevice& device, uint64_t sector) const;
     uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
@@ -306,26 +369,18 @@
     void ImportExtents(Partition* dest, const LpMetadata& metadata,
                        const LpMetadataPartition& source);
     bool ImportPartition(const LpMetadata& metadata, const LpMetadataPartition& source);
-    bool IsABDevice() const;
-    bool IsRetrofitDevice() const;
+
+    // Return true if the device is an AB device.
+    static bool IsABDevice();
+
+    // Return true if the device is retrofitting dynamic partitions.
+    static bool IsRetrofitDynamicPartitionsDevice();
+
+    // Return true if _b partitions should be prioritized at the second half of the device.
+    bool ShouldHalveSuper() const;
+
     bool ValidatePartitionGroups() const;
 
-    struct Interval {
-        uint32_t device_index;
-        uint64_t start;
-        uint64_t end;
-
-        Interval(uint32_t device_index, uint64_t start, uint64_t end)
-            : device_index(device_index), start(start), end(end) {}
-        uint64_t length() const { return end - start; }
-
-        // Note: the device index is not included in sorting (intervals are
-        // sorted in per-device lists).
-        bool operator<(const Interval& other) const {
-            return (start == other.start) ? end < other.end : start < other.start;
-        }
-    };
-    std::vector<Interval> GetFreeRegions() const;
     bool IsAnyRegionCovered(const std::vector<Interval>& regions,
                             const LinearExtent& candidate) const;
     bool IsAnyRegionAllocated(const LinearExtent& candidate) const;
@@ -336,8 +391,8 @@
                                                     const std::vector<Interval>& free_list,
                                                     uint64_t sectors_needed) const;
 
-    static bool sABOverrideValue;
-    static bool sABOverrideSet;
+    static bool UpdateMetadataForOtherSuper(LpMetadata* metadata, uint32_t source_slot_number,
+                                            uint32_t target_slot_number);
 
     LpMetadataGeometry geometry_;
     LpMetadataHeader header_;
@@ -345,7 +400,6 @@
     std::vector<std::unique_ptr<PartitionGroup>> groups_;
     std::vector<LpMetadataBlockDevice> block_devices_;
     bool auto_slot_suffixing_;
-    bool ignore_slot_suffixing_;
 };
 
 // Read BlockDeviceInfo for a given block device. This always returns false
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index 5f782b0..04f8987 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -70,11 +70,21 @@
                           uint32_t slot_number);
 std::unique_ptr<LpMetadata> ReadMetadata(const std::string& super_partition, uint32_t slot_number);
 
-// Read/Write logical partition metadata to an image file, for diagnostics or
+// Returns whether an image is an "empty" image or not. An empty image contains
+// only metadata. Unlike a flashed block device, there are no reserved bytes or
+// backup sections, and only one slot is stored (even if multiple slots are
+// supported). It is a format specifically for storing only metadata.
+bool IsEmptySuperImage(const std::string& file);
+
+// Read/Write logical partition metadata and contents to an image file, for
 // flashing.
-bool WriteToImageFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
+bool WriteToImageFile(const std::string& file, const LpMetadata& metadata, uint32_t block_size,
                       const std::map<std::string, std::string>& images, bool sparsify);
-bool WriteToImageFile(const char* file, const LpMetadata& metadata);
+
+// Read/Write logical partition metadata to an image file, for producing a
+// super_empty.img (for fastboot wipe-super/update-super) or for diagnostics.
+bool WriteToImageFile(const std::string& file, const LpMetadata& metadata);
+bool WriteToImageFile(android::base::borrowed_fd fd, const LpMetadata& metadata);
 std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file);
 std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes);
 
@@ -107,6 +117,10 @@
 std::string SlotSuffixForSlotNumber(uint32_t slot_number);
 std::string GetPartitionSlotSuffix(const std::string& partition_name);
 
+// Helpers for common functions.
+const LpMetadataPartition* FindPartition(const LpMetadata& metadata, const std::string& name);
+uint64_t GetPartitionSize(const LpMetadata& metadata, const LpMetadataPartition& partition);
+
 }  // namespace fs_mgr
 }  // namespace android
 
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 8934aaf..41d8b0c 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -39,7 +39,14 @@
 
 /* Current metadata version. */
 #define LP_METADATA_MAJOR_VERSION 10
-#define LP_METADATA_MINOR_VERSION 0
+#define LP_METADATA_MINOR_VERSION_MIN 0
+#define LP_METADATA_MINOR_VERSION_MAX 2
+
+/* Metadata version needed to use the UPDATED partition attribute. */
+#define LP_METADATA_VERSION_FOR_UPDATED_ATTR 1
+
+/* Metadata version needed for the new expanded header struct. */
+#define LP_METADATA_VERSION_FOR_EXPANDED_HEADER 2
 
 /* Attributes for the LpMetadataPartition::attributes field.
  *
@@ -58,8 +65,24 @@
  */
 #define LP_PARTITION_ATTR_SLOT_SUFFIXED (1 << 1)
 
-/* Mask that defines all valid attributes. */
-#define LP_PARTITION_ATTRIBUTE_MASK (LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED)
+/* This flag is applied automatically when using MetadataBuilder::NewForUpdate.
+ * It signals that the partition was created (or modified) for a snapshot-based
+ * update. If this flag is not present, the partition was likely flashed via
+ * fastboot.
+ */
+#define LP_PARTITION_ATTR_UPDATED (1 << 2)
+
+/* This flag marks a partition as disabled. It should not be used or mapped. */
+#define LP_PARTITION_ATTR_DISABLED (1 << 3)
+
+/* Mask that defines all valid attributes. When changing this, make sure to
+ * update ParseMetadata().
+ */
+#define LP_PARTITION_ATTRIBUTE_MASK_V0 \
+    (LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED)
+#define LP_PARTITION_ATTRIBUTE_MASK_V1 (LP_PARTITION_ATTR_UPDATED | LP_PARTITION_ATTR_DISABLED)
+#define LP_PARTITION_ATTRIBUTE_MASK \
+    (LP_PARTITION_ATTRIBUTE_MASK_V0 | LP_PARTITION_ATTRIBUTE_MASK_V1)
 
 /* Default name of the physical partition that holds logical partition entries.
  * The layout of this partition will look like:
@@ -196,8 +219,27 @@
     LpMetadataTableDescriptor groups;
     /* 116: Block device table. */
     LpMetadataTableDescriptor block_devices;
+
+    /* Everything past here is header version 1.2+, and is only included if
+     * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must
+     * zero these additional fields.
+     */
+
+    /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are
+     * independent of the version number and intended to be informational only.
+     * New flags can be added without bumping the version.
+     */
+    uint32_t flags;
+
+    /* 132: Reserved (zero), pad to 256 bytes. */
+    uint8_t reserved[124];
 } __attribute__((packed)) LpMetadataHeader;
 
+/* This device uses Virtual A/B. Note that on retrofit devices, the expanded
+ * header may not be present.
+ */
+#define LP_HEADER_FLAG_VIRTUAL_AB_DEVICE 0x1
+
 /* This struct defines a logical partition entry, similar to what would be
  * present in a GUID Partition Table.
  */
@@ -335,6 +377,25 @@
  */
 #define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0)
 
+/* For ease of writing compatibility checks, the original metadata header is
+ * preserved below, and typedefs are provided for the current version.
+ */
+typedef struct LpMetadataHeaderV1_0 {
+    uint32_t magic;
+    uint16_t major_version;
+    uint16_t minor_version;
+    uint32_t header_size;
+    uint8_t header_checksum[32];
+    uint32_t tables_size;
+    uint8_t tables_checksum[32];
+    LpMetadataTableDescriptor partitions;
+    LpMetadataTableDescriptor extents;
+    LpMetadataTableDescriptor groups;
+    LpMetadataTableDescriptor block_devices;
+} __attribute__((packed)) LpMetadataHeaderV1_0;
+
+typedef LpMetadataHeader LpMetadataHeaderV1_2;
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/fs_mgr/liblp/include/liblp/mock_property_fetcher.h b/fs_mgr/liblp/include/liblp/mock_property_fetcher.h
new file mode 100644
index 0000000..f15611b
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/mock_property_fetcher.h
@@ -0,0 +1,56 @@
+/*
+ * 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 <gmock/gmock.h>
+
+#include <liblp/property_fetcher.h>
+
+namespace android {
+namespace fs_mgr {
+namespace testing {
+
+class MockPropertyFetcher : public IPropertyFetcher {
+  public:
+    MOCK_METHOD2(GetProperty, std::string(const std::string&, const std::string&));
+    MOCK_METHOD2(GetBoolProperty, bool(const std::string&, bool));
+
+    // By default, return default_value for all functions.
+    MockPropertyFetcher() {
+        using ::testing::_;
+        using ::testing::Invoke;
+        ON_CALL(*this, GetProperty(_, _)).WillByDefault(Invoke([](const auto&, const auto& def) {
+            return def;
+        }));
+        ON_CALL(*this, GetBoolProperty(_, _)).WillByDefault(Invoke([](const auto&, auto def) {
+            return def;
+        }));
+    }
+};
+
+static inline void ResetMockPropertyFetcher() {
+    IPropertyFetcher::OverrideForTesting(
+            std::make_unique<::testing::NiceMock<MockPropertyFetcher>>());
+}
+
+static inline MockPropertyFetcher* GetMockedPropertyFetcher() {
+    return static_cast<MockPropertyFetcher*>(IPropertyFetcher::GetInstance());
+}
+
+}  // namespace testing
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/liblp/include/liblp/partition_opener.h b/fs_mgr/liblp/include/liblp/partition_opener.h
index e506bd5..7c9100b 100644
--- a/fs_mgr/liblp/include/liblp/partition_opener.h
+++ b/fs_mgr/liblp/include/liblp/partition_opener.h
@@ -62,6 +62,11 @@
     // Return block device information about the given named physical partition.
     // The name can be an absolute path if the full path is already known.
     virtual bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const = 0;
+
+    // Return a path that can be used to pass the block device to device-mapper.
+    // This must either result in an absolute path, or a major:minor device
+    // sequence.
+    virtual std::string GetDeviceString(const std::string& partition_name) const = 0;
 };
 
 // Helper class to implement IPartitionOpener. If |partition_name| is not an
@@ -71,6 +76,7 @@
     virtual android::base::unique_fd Open(const std::string& partition_name,
                                           int flags) const override;
     virtual bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const override;
+    virtual std::string GetDeviceString(const std::string& partition_name) const override;
 };
 
 }  // namespace fs_mgr
diff --git a/fs_mgr/liblp/include/liblp/property_fetcher.h b/fs_mgr/liblp/include/liblp/property_fetcher.h
new file mode 100644
index 0000000..e73a1f5
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/property_fetcher.h
@@ -0,0 +1,42 @@
+//
+// 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 <memory>
+
+namespace android {
+namespace fs_mgr {
+
+class IPropertyFetcher {
+  public:
+    virtual ~IPropertyFetcher() = default;
+    virtual std::string GetProperty(const std::string& key, const std::string& defaultValue) = 0;
+    virtual bool GetBoolProperty(const std::string& key, bool defaultValue) = 0;
+
+    static IPropertyFetcher* GetInstance();
+    static void OverrideForTesting(std::unique_ptr<IPropertyFetcher>&&);
+};
+
+class PropertyFetcher : public IPropertyFetcher {
+  public:
+    ~PropertyFetcher() = default;
+    std::string GetProperty(const std::string& key, const std::string& defaultValue) override;
+    bool GetBoolProperty(const std::string& key, bool defaultValue) override;
+};
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index fcef1f0..e67fb33 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -21,12 +21,12 @@
 
 #include <android-base/file.h>
 #include <android-base/unique_fd.h>
-#include <fs_mgr.h>
-#include <fstab/fstab.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <liblp/builder.h>
 
 #include "images.h"
+#include "liblp_test.h"
 #include "reader.h"
 #include "test_partition_opener.h"
 #include "utility.h"
@@ -34,6 +34,9 @@
 
 using namespace std;
 using namespace android::fs_mgr;
+using namespace android::fs_mgr::testing;
+using ::testing::_;
+using ::testing::Return;
 using unique_fd = android::base::unique_fd;
 
 // Our tests assume a 128KiB disk with two 512 byte metadata slots.
@@ -120,7 +123,7 @@
 }
 
 // Test that our CreateFakeDisk() function works.
-TEST(liblp, CreateFakeDisk) {
+TEST_F(LiblpTest, CreateFakeDisk) {
     unique_fd fd = CreateFakeDisk();
     ASSERT_GE(fd, 0);
 
@@ -136,7 +139,7 @@
 
 // Flashing metadata should not work if the metadata was created for a larger
 // disk than the destination disk.
-TEST(liblp, ExportDiskTooSmall) {
+TEST_F(LiblpTest, ExportDiskTooSmall) {
     unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(kDiskSize + 4096, 512, 2);
     ASSERT_NE(builder, nullptr);
     unique_ptr<LpMetadata> exported = builder->Export();
@@ -153,7 +156,7 @@
 }
 
 // Test the basics of flashing a partition and reading it back.
-TEST(liblp, FlashAndReadback) {
+TEST_F(LiblpTest, FlashAndReadback) {
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
     ASSERT_NE(builder, nullptr);
     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
@@ -203,7 +206,7 @@
 }
 
 // Test that we can update metadata slots without disturbing others.
-TEST(liblp, UpdateAnyMetadataSlot) {
+TEST_F(LiblpTest, UpdateAnyMetadataSlot) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -248,7 +251,7 @@
     }
 }
 
-TEST(liblp, InvalidMetadataSlot) {
+TEST_F(LiblpTest, InvalidMetadataSlot) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -267,7 +270,7 @@
 
 // Test that updating a metadata slot does not allow it to be computed based
 // on mismatching geometry.
-TEST(liblp, NoChangingGeometry) {
+TEST_F(LiblpTest, NoChangingGeometry) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -296,7 +299,7 @@
 }
 
 // Test that changing one bit of metadata is enough to break the checksum.
-TEST(liblp, BitFlipGeometry) {
+TEST_F(LiblpTest, BitFlipGeometry) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -315,7 +318,7 @@
     EXPECT_EQ(metadata->geometry.metadata_slot_count, 2);
 }
 
-TEST(liblp, ReadBackupGeometry) {
+TEST_F(LiblpTest, ReadBackupGeometry) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -335,7 +338,7 @@
     EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
 }
 
-TEST(liblp, ReadBackupMetadata) {
+TEST_F(LiblpTest, ReadBackupMetadata) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -362,14 +365,14 @@
 
 // Test that we don't attempt to write metadata if it would overflow its
 // reserved space.
-TEST(liblp, TooManyPartitions) {
+TEST_F(LiblpTest, TooManyPartitions) {
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
     ASSERT_NE(builder, nullptr);
 
     // Compute the maximum number of partitions we can fit in 512 bytes of
     // metadata. By default there is the header, one partition group, and a
     // block device entry.
-    static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeader) -
+    static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeaderV1_0) -
                                                  sizeof(LpMetadataPartitionGroup) -
                                                  sizeof(LpMetadataBlockDevice);
     size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition);
@@ -416,7 +419,7 @@
 }
 
 // Test that we can read and write image files.
-TEST(liblp, ImageFiles) {
+TEST_F(LiblpTest, ImageFiles) {
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
     ASSERT_NE(builder, nullptr);
     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
@@ -432,7 +435,7 @@
 }
 
 // Test that we can read images from buffers.
-TEST(liblp, ImageFilesInMemory) {
+TEST_F(LiblpTest, ImageFilesInMemory) {
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
     ASSERT_NE(builder, nullptr);
     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
@@ -492,7 +495,7 @@
 
 // Test that an interrupted flash operation on the "primary" copy of metadata
 // is not fatal.
-TEST(liblp, UpdatePrimaryMetadataFailure) {
+TEST_F(LiblpTest, UpdatePrimaryMetadataFailure) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -520,7 +523,7 @@
 
 // Test that an interrupted flash operation on the "backup" copy of metadata
 // is not fatal.
-TEST(liblp, UpdateBackupMetadataFailure) {
+TEST_F(LiblpTest, UpdateBackupMetadataFailure) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -549,7 +552,7 @@
 // Test that an interrupted write *in between* writing metadata will read
 // the correct metadata copy. The primary is always considered newer than
 // the backup.
-TEST(liblp, UpdateMetadataCleanFailure) {
+TEST_F(LiblpTest, UpdateMetadataCleanFailure) {
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -586,7 +589,7 @@
 }
 
 // Test that writing a sparse image can be read back.
-TEST(liblp, FlashSparseImage) {
+TEST_F(LiblpTest, FlashSparseImage) {
     unique_fd fd = CreateFakeDisk();
     ASSERT_GE(fd, 0);
 
@@ -620,7 +623,7 @@
     ASSERT_NE(ReadBackupMetadata(fd.get(), geometry, 0), nullptr);
 }
 
-TEST(liblp, AutoSlotSuffixing) {
+TEST_F(LiblpTest, AutoSlotSuffixing) {
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
     ASSERT_NE(builder, nullptr);
     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
@@ -663,7 +666,10 @@
     EXPECT_EQ(metadata->groups[1].flags, 0);
 }
 
-TEST(liblp, UpdateRetrofit) {
+TEST_F(LiblpTest, UpdateRetrofit) {
+    ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+            .WillByDefault(Return(true));
+
     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
     ASSERT_NE(builder, nullptr);
     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
@@ -692,7 +698,10 @@
     ASSERT_TRUE(updated->extents.empty());
 }
 
-TEST(liblp, UpdateNonRetrofit) {
+TEST_F(LiblpTest, UpdateNonRetrofit) {
+    ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+            .WillByDefault(Return(false));
+
     unique_fd fd = CreateFlashedDisk();
     ASSERT_GE(fd, 0);
 
@@ -705,18 +714,56 @@
     EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super");
 }
 
-TEST(liblp, ReadSuperPartition) {
-    auto slot_suffix = fs_mgr_get_slot_suffix();
-    auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
-    auto super_name = fs_mgr_get_super_partition_name(slot_number);
-    auto metadata = ReadMetadata(super_name, slot_number);
-    ASSERT_NE(metadata, nullptr);
+TEST_F(LiblpTest, UpdateVirtualAB) {
+    ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.virtual_ab.enabled", _))
+            .WillByDefault(Return(true));
 
-    if (!slot_suffix.empty()) {
-        auto other_slot_suffix = fs_mgr_get_other_slot_suffix();
-        auto other_slot_number = SlotNumberForSlotSuffix(other_slot_suffix);
-        auto other_super_name = fs_mgr_get_super_partition_name(other_slot_number);
-        auto other_metadata = ReadMetadata(other_super_name, other_slot_number);
-        ASSERT_NE(other_metadata, nullptr);
-    }
+    unique_fd fd = CreateFlashedDisk();
+    ASSERT_GE(fd, 0);
+
+    DefaultPartitionOpener opener(fd);
+    auto builder = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
+    ASSERT_NE(builder, nullptr);
+    auto updated = builder->Export();
+    ASSERT_NE(updated, nullptr);
+    ASSERT_TRUE(UpdatePartitionTable(opener, "super", *updated.get(), 1));
+
+    // Validate old slot.
+    auto metadata = ReadMetadata(opener, "super", 0);
+    ASSERT_NE(metadata, nullptr);
+    ASSERT_EQ(metadata->header.minor_version, 0);
+    ASSERT_GE(metadata->partitions.size(), 1);
+    ASSERT_EQ(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0);
+
+    // Validate new slot.
+    metadata = ReadMetadata(opener, "super", 1);
+    ASSERT_NE(metadata, nullptr);
+    ASSERT_EQ(metadata->header.minor_version, 1);
+    ASSERT_GE(metadata->partitions.size(), 1);
+    ASSERT_NE(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0);
+}
+
+TEST_F(LiblpTest, ReadExpandedHeader) {
+    unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
+    ASSERT_NE(builder, nullptr);
+    ASSERT_TRUE(AddDefaultPartitions(builder.get()));
+
+    builder->RequireExpandedMetadataHeader();
+
+    unique_fd fd = CreateFakeDisk();
+    ASSERT_GE(fd, 0);
+
+    DefaultPartitionOpener opener(fd);
+
+    // Export and flash.
+    unique_ptr<LpMetadata> exported = builder->Export();
+    ASSERT_NE(exported, nullptr);
+    exported->header.flags = 0x5e5e5e5e;
+    ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
+
+    unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
+    ASSERT_NE(imported, nullptr);
+    EXPECT_EQ(imported->header.header_size, sizeof(LpMetadataHeaderV1_2));
+    EXPECT_EQ(imported->header.header_size, exported->header.header_size);
+    EXPECT_EQ(imported->header.flags, exported->header.flags);
 }
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/fs_mgr/liblp/liblp_test.h
similarity index 68%
rename from libmeminfo/vts/vts_meminfo_test.cpp
rename to fs_mgr/liblp/liblp_test.h
index 3193c31..c61aaa5 100644
--- a/libmeminfo/vts/vts_meminfo_test.cpp
+++ b/fs_mgr/liblp/liblp_test.h
@@ -14,18 +14,22 @@
  * limitations under the License.
  */
 
+#pragma once
+
 #include <gtest/gtest.h>
 
-#include <meminfo/procmeminfo.h>
+#include <liblp/mock_property_fetcher.h>
 
 namespace android {
-namespace meminfo {
+namespace fs_mgr {
+namespace testing {
 
-// /proc/<pid>/smaps_rollup support is required.
-TEST(SmapsRollup, IsSupported) {
-    // Use init's pid for this test since it's the only known pid.
-    ASSERT_TRUE(IsSmapsRollupSupported(1));
-}
+class LiblpTest : public ::testing::Test {
+  public:
+    void SetUp() override { ResetMockPropertyFetcher(); }
+    void TearDown() override { ResetMockPropertyFetcher(); }
+};
 
-}  // namespace meminfo
+}  // namespace testing
+}  // namespace fs_mgr
 }  // namespace android
diff --git a/libmemunreachable/tests/AndroidTest.xml b/fs_mgr/liblp/liblp_test.xml
similarity index 70%
rename from libmemunreachable/tests/AndroidTest.xml
rename to fs_mgr/liblp/liblp_test.xml
index 604c0ec..d9ee12e 100644
--- a/libmemunreachable/tests/AndroidTest.xml
+++ b/fs_mgr/liblp/liblp_test.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<!-- 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.
@@ -13,14 +13,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Config for memunreachable_test">
+<configuration description="Config for liblp_test">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push" value="memunreachable_test->/data/local/tmp/memunreachable_test" />
+        <option name="push" value="liblp_test->/data/local/tmp/liblp_test" />
     </target_preparer>
-    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="vts-core" />
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="memunreachable_test" />
+        <option name="module-name" value="liblp_test" />
     </test>
 </configuration>
diff --git a/fs_mgr/liblp/partition_opener.cpp b/fs_mgr/liblp/partition_opener.cpp
index bb8ec9c..1d4db85 100644
--- a/fs_mgr/liblp/partition_opener.cpp
+++ b/fs_mgr/liblp/partition_opener.cpp
@@ -26,6 +26,7 @@
 #include <unistd.h>
 
 #include <android-base/file.h>
+#include <android-base/strings.h>
 
 #include "utility.h"
 
@@ -37,10 +38,24 @@
 namespace {
 
 std::string GetPartitionAbsolutePath(const std::string& path) {
-    if (path[0] == '/') {
+    if (android::base::StartsWith(path, "/")) {
         return path;
     }
-    return "/dev/block/by-name/" + path;
+
+    auto by_name = "/dev/block/by-name/" + path;
+    if (access(by_name.c_str(), F_OK) != 0) {
+        // If the by-name symlink doesn't exist, as a special case we allow
+        // certain devices to be used as partition names. This can happen if a
+        // Dynamic System Update is installed to an sdcard, which won't be in
+        // the boot device list.
+        //
+        // We whitelist because most devices in /dev/block are not valid for
+        // storing fiemaps.
+        if (android::base::StartsWith(path, "mmcblk")) {
+            return "/dev/block/" + path;
+        }
+    }
+    return by_name;
 }
 
 bool GetBlockDeviceInfo(const std::string& block_device, BlockDeviceInfo* device_info) {
@@ -63,6 +78,12 @@
         PERROR << __PRETTY_FUNCTION__ << "BLKALIGNOFF failed on " << block_device;
         return false;
     }
+    // The kernel can return -1 here when misaligned devices are stacked (i.e.
+    // device-mapper).
+    if (alignment_offset == -1) {
+        alignment_offset = 0;
+    }
+
     int logical_block_size;
     if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
         PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed on " << block_device;
@@ -93,5 +114,9 @@
     return GetBlockDeviceInfo(path, info);
 }
 
+std::string PartitionOpener::GetDeviceString(const std::string& partition_name) const {
+    return GetPartitionAbsolutePath(partition_name);
+}
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/property_fetcher.cpp b/fs_mgr/liblp/property_fetcher.cpp
new file mode 100644
index 0000000..038ef4d
--- /dev/null
+++ b/fs_mgr/liblp/property_fetcher.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "liblp/property_fetcher.h"
+
+#include <memory>
+
+#include <android-base/properties.h>
+
+namespace android {
+namespace fs_mgr {
+
+std::string PropertyFetcher::GetProperty(const std::string& key, const std::string& default_value) {
+    return android::base::GetProperty(key, default_value);
+}
+
+bool PropertyFetcher::GetBoolProperty(const std::string& key, bool default_value) {
+    return android::base::GetBoolProperty(key, default_value);
+}
+
+static std::unique_ptr<IPropertyFetcher>* GetInstanceAllocation() {
+    static std::unique_ptr<IPropertyFetcher> instance = std::make_unique<PropertyFetcher>();
+    return &instance;
+}
+
+IPropertyFetcher* IPropertyFetcher::GetInstance() {
+    return GetInstanceAllocation()->get();
+}
+
+void IPropertyFetcher::OverrideForTesting(std::unique_ptr<IPropertyFetcher>&& fetcher) {
+    GetInstanceAllocation()->swap(fetcher);
+    fetcher.reset();
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index dcee6d2..e6fd9f7 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -18,6 +18,7 @@
 
 #include <stddef.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 #include <functional>
@@ -30,6 +31,9 @@
 namespace android {
 namespace fs_mgr {
 
+static_assert(sizeof(LpMetadataHeaderV1_0) == offsetof(LpMetadataHeader, flags),
+              "Incorrect LpMetadataHeader v0 size");
+
 // Helper class for reading descriptors and memory buffers in the same manner.
 class Reader {
   public:
@@ -160,30 +164,59 @@
     return true;
 }
 
-static bool ValidateMetadataHeader(const LpMetadataHeader& header) {
+static bool ReadMetadataHeader(Reader* reader, LpMetadata* metadata) {
+    // Note we zero the struct since older files will result in a partial read.
+    LpMetadataHeader& header = metadata->header;
+    memset(&header, 0, sizeof(header));
+
+    if (!reader->ReadFully(&header, sizeof(LpMetadataHeaderV1_0))) {
+        PERROR << __PRETTY_FUNCTION__ << " read failed";
+        return false;
+    }
+
+    // Do basic sanity checks before computing the checksum.
+    if (header.magic != LP_METADATA_HEADER_MAGIC) {
+        LERROR << "Logical partition metadata has invalid magic value.";
+        return false;
+    }
+    if (header.major_version != LP_METADATA_MAJOR_VERSION ||
+        header.minor_version > LP_METADATA_MINOR_VERSION_MAX) {
+        LERROR << "Logical partition metadata has incompatible version.";
+        return false;
+    }
+
+    // Validate the header struct size against the reported version.
+    uint32_t expected_struct_size = sizeof(header);
+    if (header.minor_version < LP_METADATA_VERSION_FOR_EXPANDED_HEADER) {
+        expected_struct_size = sizeof(LpMetadataHeaderV1_0);
+    }
+    if (header.header_size != expected_struct_size) {
+        LERROR << "Invalid partition metadata header struct size.";
+        return false;
+    }
+
+    // Read in any remaining fields, the last step needed before checksumming.
+    if (size_t remaining_bytes = header.header_size - sizeof(LpMetadataHeaderV1_0)) {
+        uint8_t* offset = reinterpret_cast<uint8_t*>(&header) + sizeof(LpMetadataHeaderV1_0);
+        if (!reader->ReadFully(offset, remaining_bytes)) {
+            PERROR << __PRETTY_FUNCTION__ << " read failed";
+            return false;
+        }
+    }
+
     // To compute the header's checksum, we have to temporarily set its checksum
-    // field to 0.
+    // field to 0. Note that we must only compute up to |header_size|.
     {
         LpMetadataHeader temp = header;
         memset(&temp.header_checksum, 0, sizeof(temp.header_checksum));
-        SHA256(&temp, sizeof(temp), temp.header_checksum);
-        if (memcmp(temp.header_checksum, header.header_checksum, sizeof(temp.header_checksum)) != 0) {
+        SHA256(&temp, temp.header_size, temp.header_checksum);
+        if (memcmp(temp.header_checksum, header.header_checksum, sizeof(temp.header_checksum)) !=
+            0) {
             LERROR << "Logical partition metadata has invalid checksum.";
             return false;
         }
     }
 
-    // Do basic validation of key metadata bits.
-    if (header.magic != LP_METADATA_HEADER_MAGIC) {
-        LERROR << "Logical partition metadata has invalid magic value.";
-        return false;
-    }
-    // Check that the version is compatible.
-    if (header.major_version != LP_METADATA_MAJOR_VERSION ||
-        header.minor_version > LP_METADATA_MINOR_VERSION) {
-        LERROR << "Logical partition metadata has incompatible version.";
-        return false;
-    }
     if (!ValidateTableBounds(header, header.partitions) ||
         !ValidateTableBounds(header, header.extents) ||
         !ValidateTableBounds(header, header.groups) ||
@@ -214,19 +247,22 @@
                                                  Reader* reader) {
     // First read and validate the header.
     std::unique_ptr<LpMetadata> metadata = std::make_unique<LpMetadata>();
-    if (!reader->ReadFully(&metadata->header, sizeof(metadata->header))) {
-        PERROR << __PRETTY_FUNCTION__ << " read " << sizeof(metadata->header) << "bytes failed";
-        return nullptr;
-    }
-    if (!ValidateMetadataHeader(metadata->header)) {
-        return nullptr;
-    }
+
     metadata->geometry = geometry;
+    if (!ReadMetadataHeader(reader, metadata.get())) {
+        return nullptr;
+    }
 
     LpMetadataHeader& header = metadata->header;
 
-    // Read the metadata payload. Allocation is fallible in case the metadata is
-    // corrupt and has some huge value.
+    // Sanity check the table size.
+    if (header.tables_size > geometry.metadata_max_size) {
+        LERROR << "Invalid partition metadata header table size.";
+        return nullptr;
+    }
+
+    // Read the metadata payload. Allocation is fallible since the table size
+    // could be large.
     std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[header.tables_size]);
     if (!buffer) {
         LERROR << "Out of memory reading logical partition tables.";
@@ -244,6 +280,11 @@
         return nullptr;
     }
 
+    uint32_t valid_attributes = LP_PARTITION_ATTRIBUTE_MASK_V0;
+    if (metadata->header.minor_version >= LP_METADATA_VERSION_FOR_UPDATED_ATTR) {
+        valid_attributes |= LP_PARTITION_ATTRIBUTE_MASK_V1;
+    }
+
     // ValidateTableSize ensured that |cursor| is valid for the number of
     // entries in the table.
     uint8_t* cursor = buffer.get() + header.partitions.offset;
@@ -252,7 +293,7 @@
         memcpy(&partition, cursor, sizeof(partition));
         cursor += header.partitions.entry_size;
 
-        if (partition.attributes & ~LP_PARTITION_ATTRIBUTE_MASK) {
+        if (partition.attributes & ~valid_attributes) {
             LERROR << "Logical partition has invalid attribute set.";
             return nullptr;
         }
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 72a3c57..48c5c83 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -24,6 +24,10 @@
 #include <sys/ioctl.h>
 #endif
 
+#include <map>
+#include <string>
+#include <vector>
+
 #include <android-base/file.h>
 #include <ext4_utils/ext4_utils.h>
 #include <openssl/sha.h>
@@ -135,6 +139,24 @@
     return list;
 }
 
+const LpMetadataPartition* FindPartition(const LpMetadata& metadata, const std::string& name) {
+    for (const auto& partition : metadata.partitions) {
+        if (GetPartitionName(partition) == name) {
+            return &partition;
+        }
+    }
+    return nullptr;
+}
+
+uint64_t GetPartitionSize(const LpMetadata& metadata, const LpMetadataPartition& partition) {
+    uint64_t total_size = 0;
+    for (uint32_t i = 0; i < partition.num_extents; i++) {
+        const auto& extent = metadata.extents[partition.first_extent_index + i];
+        total_size += extent.num_sectors * LP_SECTOR_SIZE;
+    }
+    return total_size;
+}
+
 std::string GetPartitionSlotSuffix(const std::string& partition_name) {
     if (partition_name.size() <= 2) {
         return "";
@@ -164,6 +186,14 @@
     return true;
 }
 
+bool UpdatePartitionName(LpMetadataPartition* partition, const std::string& name) {
+    if (name.size() > sizeof(partition->name)) {
+        return false;
+    }
+    strncpy(partition->name, name.c_str(), sizeof(partition->name));
+    return true;
+}
+
 bool SetBlockReadonly(int fd, bool readonly) {
 #if defined(__linux__)
     int val = readonly;
@@ -175,9 +205,9 @@
 #endif
 }
 
-base::unique_fd GetControlFileOrOpen(const char* path, int flags) {
+base::unique_fd GetControlFileOrOpen(std::string_view path, int flags) {
 #if defined(__ANDROID__)
-    int fd = android_get_control_file(path);
+    int fd = android_get_control_file(path.data());
     if (fd >= 0) {
         int newfd = TEMP_FAILURE_RETRY(dup(fd));
         if (newfd >= 0) {
@@ -186,7 +216,73 @@
         PERROR << "Cannot dup fd for already controlled file: " << path << ", reopening...";
     }
 #endif
-    return base::unique_fd(open(path, flags));
+    return base::unique_fd(open(path.data(), flags));
+}
+
+bool UpdateMetadataForInPlaceSnapshot(LpMetadata* metadata, uint32_t source_slot_number,
+                                      uint32_t target_slot_number) {
+    std::string source_slot_suffix = SlotSuffixForSlotNumber(source_slot_number);
+    std::string target_slot_suffix = SlotSuffixForSlotNumber(target_slot_number);
+
+    // There can be leftover groups with target suffix on retrofit devices.
+    // They are useless now, so delete.
+    std::vector<LpMetadataPartitionGroup*> new_group_ptrs;
+    for (auto& group : metadata->groups) {
+        std::string group_name = GetPartitionGroupName(group);
+        std::string slot_suffix = GetPartitionSlotSuffix(group_name);
+        // Don't add groups with target slot suffix.
+        if (slot_suffix == target_slot_suffix) continue;
+        // Replace source slot suffix with target slot suffix.
+        if (slot_suffix == source_slot_suffix) {
+            std::string new_name = group_name.substr(0, group_name.size() - slot_suffix.size()) +
+                                   target_slot_suffix;
+            if (!UpdatePartitionGroupName(&group, new_name)) {
+                LERROR << "Group name too long: " << new_name;
+                return false;
+            }
+        }
+        new_group_ptrs.push_back(&group);
+    }
+
+    std::vector<LpMetadataPartition*> new_partition_ptrs;
+    for (auto& partition : metadata->partitions) {
+        std::string partition_name = GetPartitionName(partition);
+        std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
+        // Don't add partitions with target slot suffix.
+        if (slot_suffix == target_slot_suffix) continue;
+        // Replace source slot suffix with target slot suffix.
+        if (slot_suffix == source_slot_suffix) {
+            std::string new_name =
+                    partition_name.substr(0, partition_name.size() - slot_suffix.size()) +
+                    target_slot_suffix;
+            if (!UpdatePartitionName(&partition, new_name)) {
+                LERROR << "Partition name too long: " << new_name;
+                return false;
+            }
+        }
+        // Update group index.
+        auto it = std::find(new_group_ptrs.begin(), new_group_ptrs.end(),
+                            &metadata->groups[partition.group_index]);
+        if (it == new_group_ptrs.end()) {
+            LWARN << "Removing partition " << partition_name << " from group "
+                  << GetPartitionGroupName(metadata->groups[partition.group_index])
+                  << "; this partition should not belong to this group!";
+            continue;  // not adding to new_partition_ptrs
+        }
+        partition.attributes |= LP_PARTITION_ATTR_UPDATED;
+        partition.group_index = std::distance(new_group_ptrs.begin(), it);
+        new_partition_ptrs.push_back(&partition);
+    }
+
+    std::vector<LpMetadataPartition> new_partitions;
+    for (auto* p : new_partition_ptrs) new_partitions.emplace_back(std::move(*p));
+    metadata->partitions = std::move(new_partitions);
+
+    std::vector<LpMetadataPartitionGroup> new_groups;
+    for (auto* g : new_group_ptrs) new_groups.emplace_back(std::move(*g));
+    metadata->groups = std::move(new_groups);
+
+    return true;
 }
 
 }  // namespace fs_mgr
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index 96f1717..0661769 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -21,6 +21,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <string>
+#include <string_view>
+
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 
@@ -89,11 +92,16 @@
 // Update names from C++ strings.
 bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::string& name);
 bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name);
+bool UpdatePartitionName(LpMetadataPartition* partition, const std::string& name);
 
 // Call BLKROSET ioctl on fd so that fd is readonly / read-writable.
 bool SetBlockReadonly(int fd, bool readonly);
 
-::android::base::unique_fd GetControlFileOrOpen(const char* path, int flags);
+::android::base::unique_fd GetControlFileOrOpen(std::string_view path, int flags);
+
+// For Virtual A/B updates, modify |metadata| so that it can be written to |target_slot_number|.
+bool UpdateMetadataForInPlaceSnapshot(LpMetadata* metadata, uint32_t source_slot_number,
+                                      uint32_t target_slot_number);
 
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 15f7fff..cac3989 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <gtest/gtest.h>
+#include <liblp/builder.h>
 #include <liblp/liblp.h>
 
 #include "utility.h"
@@ -75,3 +76,81 @@
     EXPECT_EQ(GetPartitionSlotSuffix("system_a"), "_a");
     EXPECT_EQ(GetPartitionSlotSuffix("system_b"), "_b");
 }
+
+namespace android {
+namespace fs_mgr {
+// Equality comparison for testing. In reality, equality of device_index doesn't
+// necessary mean equality of the block device.
+bool operator==(const LinearExtent& l, const LinearExtent& r) {
+    return l.device_index() == r.device_index() && l.physical_sector() == r.physical_sector() &&
+           l.end_sector() == r.end_sector();
+}
+}  // namespace fs_mgr
+}  // namespace android
+
+static std::vector<LinearExtent> GetPartitionExtents(Partition* p) {
+    std::vector<LinearExtent> extents;
+    for (auto&& extent : p->extents()) {
+        auto linear_extent = extent->AsLinearExtent();
+        if (!linear_extent) return {};
+        extents.push_back(*linear_extent);
+    }
+    return extents;
+}
+
+TEST(liblp, UpdateMetadataForInPlaceSnapshot) {
+    using std::unique_ptr;
+
+    unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
+    ASSERT_NE(builder, nullptr);
+
+    ASSERT_TRUE(builder->AddGroup("group_a", 256 * 1024));
+    Partition* system_a = builder->AddPartition("system_a", "group_a", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(system_a, nullptr);
+    ASSERT_TRUE(builder->ResizePartition(system_a, 40 * 1024));
+    Partition* vendor_a = builder->AddPartition("vendor_a", "group_a", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(vendor_a, nullptr);
+    ASSERT_TRUE(builder->ResizePartition(vendor_a, 20 * 1024));
+
+    ASSERT_TRUE(builder->AddGroup("group_b", 258 * 1024));
+    Partition* system_b = builder->AddPartition("system_b", "group_b", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(system_b, nullptr);
+    ASSERT_TRUE(builder->ResizePartition(system_b, 36 * 1024));
+    Partition* vendor_b = builder->AddPartition("vendor_b", "group_b", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(vendor_b, nullptr);
+    ASSERT_TRUE(builder->ResizePartition(vendor_b, 32 * 1024));
+
+    auto system_a_extents = GetPartitionExtents(system_a);
+    ASSERT_FALSE(system_a_extents.empty());
+
+    auto vendor_a_extents = GetPartitionExtents(vendor_a);
+    ASSERT_FALSE(vendor_a_extents.empty());
+
+    auto metadata = builder->Export();
+    ASSERT_NE(nullptr, metadata);
+
+    ASSERT_TRUE(UpdateMetadataForInPlaceSnapshot(metadata.get(), 0, 1));
+
+    auto new_builder = MetadataBuilder::New(*metadata);
+    ASSERT_NE(nullptr, new_builder);
+
+    EXPECT_EQ(nullptr, new_builder->FindGroup("group_a"));
+    EXPECT_EQ(nullptr, new_builder->FindPartition("system_a"));
+    EXPECT_EQ(nullptr, new_builder->FindPartition("vendor_a"));
+
+    auto group_b = new_builder->FindGroup("group_b");
+    ASSERT_NE(nullptr, group_b);
+    ASSERT_EQ(256 * 1024, group_b->maximum_size());
+
+    auto new_system_b = new_builder->FindPartition("system_b");
+    ASSERT_NE(nullptr, new_system_b);
+    EXPECT_EQ(40 * 1024, new_system_b->size());
+    auto new_system_b_extents = GetPartitionExtents(new_system_b);
+    EXPECT_EQ(system_a_extents, new_system_b_extents);
+
+    auto new_vendor_b = new_builder->FindPartition("vendor_b");
+    ASSERT_NE(nullptr, new_vendor_b);
+    EXPECT_EQ(20 * 1024, new_vendor_b->size());
+    auto new_vendor_b_extents = GetPartitionExtents(new_vendor_b);
+    EXPECT_EQ(vendor_a_extents, new_vendor_b_extents);
+}
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index bffcb7e..8bf1ee9 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -17,6 +17,7 @@
 #include "writer.h"
 
 #include <inttypes.h>
+#include <string.h>
 #include <unistd.h>
 
 #include <string>
@@ -73,17 +74,18 @@
 
     // Compute header checksum.
     memset(header.header_checksum, 0, sizeof(header.header_checksum));
-    SHA256(&header, sizeof(header), header.header_checksum);
+    SHA256(&header, header.header_size, header.header_checksum);
 
     std::string header_blob =
-            std::string(reinterpret_cast<const char*>(&metadata.header), sizeof(metadata.header));
+            std::string(reinterpret_cast<const char*>(&header), header.header_size);
     return header_blob + tables;
 }
 
 // Perform sanity checks so we don't accidentally overwrite valid metadata
 // with potentially invalid metadata, or random partition data with metadata.
-static bool ValidateAndSerializeMetadata(const IPartitionOpener& opener, const LpMetadata& metadata,
-                                         const std::string& slot_suffix, std::string* blob) {
+static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener,
+                                         const LpMetadata& metadata, const std::string& slot_suffix,
+                                         std::string* blob) {
     const LpMetadataGeometry& geometry = metadata.geometry;
 
     *blob = SerializeMetadata(metadata);
@@ -127,6 +129,10 @@
                    << block_device.first_logical_sector << " for size " << block_device.size;
             return false;
         }
+
+        // When flashing on the device, check partition sizes. Don't do this on
+        // the host since there is no way to verify.
+#if defined(__ANDROID__)
         BlockDeviceInfo info;
         if (!opener.GetInfo(partition_name, &info)) {
             PERROR << partition_name << ": ioctl";
@@ -137,6 +143,7 @@
                    << block_device.size << ", got " << info.size << ")";
             return false;
         }
+#endif
     }
 
     // Make sure all partition entries reference valid extents.
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
new file mode 100644
index 0000000..eadcecc
--- /dev/null
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -0,0 +1,213 @@
+//
+// 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.
+//
+
+cc_defaults {
+    name: "libsnapshot_defaults",
+    defaults: ["fs_mgr_defaults"],
+    cflags: [
+        "-D_FILE_OFFSET_BITS=64",
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "liblp",
+    ],
+    static_libs: [
+        "libcutils",
+        "libdm",
+        "libfstab",
+        "liblp",
+        "update_metadata-protos",
+    ],
+    whole_static_libs: [
+        "libext2_uuid",
+        "libext4_utils",
+        "libfstab",
+    ],
+    header_libs: [
+        "libfiemap_headers",
+    ],
+    export_static_lib_headers: [
+        "update_metadata-protos",
+    ],
+    export_header_lib_headers: [
+        "libfiemap_headers",
+    ],
+    export_include_dirs: ["include"],
+    proto: {
+        type: "lite",
+        export_proto_headers: true,
+        canonical_path_from_root: false,
+    },
+}
+
+cc_defaults {
+    name: "libsnapshot_hal_deps",
+    cflags: [
+        "-DLIBSNAPSHOT_USE_HAL",
+    ],
+    shared_libs: [
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+    ],
+}
+
+filegroup {
+    name: "libsnapshot_sources",
+    srcs: [
+        "android/snapshot/snapshot.proto",
+        "device_info.cpp",
+        "snapshot.cpp",
+        "snapshot_metadata_updater.cpp",
+        "partition_cow_creator.cpp",
+        "utility.cpp",
+    ],
+}
+
+cc_library_headers {
+    name: "libsnapshot_headers",
+    recovery_available: true,
+    defaults: ["libsnapshot_defaults"],
+}
+
+cc_library_static {
+    name: "libsnapshot",
+    defaults: [
+        "libsnapshot_defaults",
+        "libsnapshot_hal_deps",
+    ],
+    srcs: [":libsnapshot_sources"],
+    static_libs: [
+        "libfs_mgr_binder"
+    ],
+}
+
+cc_library_static {
+    name: "libsnapshot_init",
+    defaults: ["libsnapshot_defaults"],
+    srcs: [":libsnapshot_sources"],
+    recovery_available: true,
+    static_libs: [
+        "libfs_mgr",
+    ],
+}
+
+cc_library_static {
+    name: "libsnapshot_nobinder",
+    defaults: [
+        "libsnapshot_defaults",
+        "libsnapshot_hal_deps",
+    ],
+    srcs: [":libsnapshot_sources"],
+    recovery_available: true,
+    static_libs: [
+        "libfs_mgr",
+    ],
+}
+
+cc_library_static {
+    name: "libsnapshot_test_helpers",
+    defaults: ["libsnapshot_defaults"],
+    export_include_dirs: [
+        "include_test",
+    ],
+    srcs: [
+        "test_helpers.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.boot@1.1",
+        "libcrypto",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.boot@1.1",
+    ],
+    header_libs: [
+        "libstorage_literals_headers",
+    ],
+    export_header_lib_headers: [
+        "libstorage_literals_headers",
+    ],
+    static_libs: [
+        "libfs_mgr",
+        "libgtest",
+        "libgmock",
+    ],
+}
+
+cc_test {
+    name: "libsnapshot_test",
+    defaults: ["libsnapshot_defaults"],
+    srcs: [
+        "snapshot_test.cpp",
+        "partition_cow_creator_test.cpp",
+        "snapshot_metadata_updater_test.cpp",
+        "test_helpers.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "libhidlbase",
+        "libprotobuf-cpp-lite",
+        "libutils",
+    ],
+    static_libs: [
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+        "libfs_mgr",
+        "libgmock",
+        "libgsi",
+        "liblp",
+        "libsnapshot",
+        "libsnapshot_test_helpers",
+        "libsparse",
+        "libz",
+    ],
+    header_libs: [
+        "libstorage_literals_headers",
+    ],
+}
+
+cc_binary {
+    name: "snapshotctl",
+    srcs: [
+        "snapshotctl.cpp",
+    ],
+    static_libs: [
+        "libdm",
+        "libext2_uuid",
+        "libfstab",
+        "libsnapshot",
+    ],
+    shared_libs: [
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+        "libbase",
+        "libbinder",
+        "libbinderthreadstate",
+        "libext4_utils",
+        "libfs_mgr_binder",
+        "libhidlbase",
+        "liblog",
+        "liblp",
+        "libprotobuf-cpp-lite",
+        "libutils",
+    ],
+    init_rc: [
+        "snapshotctl.rc",
+    ],
+}
diff --git a/fs_mgr/libsnapshot/OWNERS b/fs_mgr/libsnapshot/OWNERS
new file mode 100644
index 0000000..0cfa7e4
--- /dev/null
+++ b/fs_mgr/libsnapshot/OWNERS
@@ -0,0 +1,2 @@
+dvander@google.com
+elsk@google.com
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
new file mode 100644
index 0000000..629c3a4
--- /dev/null
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -0,0 +1,87 @@
+// 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.
+
+syntax = "proto3";
+package android.snapshot;
+
+option optimize_for = LITE_RUNTIME;
+
+// Next: 4
+enum SnapshotState {
+    // No snapshot is found.
+    NONE = 0;
+
+    // The snapshot has been created and possibly written to. Rollbacks are
+    // possible by destroying the snapshot.
+    CREATED = 1;
+
+    // Changes are being merged. No rollbacks are possible beyond this point.
+    MERGING = 2;
+
+    // Changes have been merged, Future reboots may map the base device
+    // directly.
+    MERGE_COMPLETED = 3;
+}
+
+// Next: 9
+message SnapshotStatus {
+    // Name of the snapshot. This is usually the name of the snapshotted
+    // logical partition; for example, "system_b".
+    string name = 1;
+
+    SnapshotState state = 2;
+
+    // Size of the full (base) device.
+    uint64 device_size = 3;
+
+    // Size of the snapshot. This is the sum of lengths of ranges in the base
+    // device that needs to be snapshotted during the update.
+    // This must be less than or equal to |device_size|.
+    // This value is 0 if no snapshot is needed for this device because
+    // no changes
+    uint64 snapshot_size = 4;
+
+    // Size of the "COW partition". A COW partition is a special logical
+    // partition represented in the super partition metadata. This partition and
+    // the "COW image" form the "COW device" that supports the snapshot device.
+    //
+    // When SnapshotManager creates a COW device, it first searches for unused
+    // blocks in the super partition, and use those before creating the COW
+    // image if the COW partition is not big enough.
+    //
+    // This value is 0 if no space in super is left for the COW partition.
+    // |cow_partition_size + cow_file_size| must not be zero if |snapshot_size|
+    // is non-zero.
+    uint64 cow_partition_size = 5;
+
+    // Size of the "COW file", or "COW image". A COW file / image is created
+    // when the "COW partition" is not big enough to store changes to the
+    // snapshot device.
+    //
+    // This value is 0 if |cow_partition_size| is big enough to hold all changes
+    // to the snapshot device.
+    uint64 cow_file_size = 6;
+
+    // Sectors allocated for the COW device. Recording this value right after
+    // the update and before the merge allows us to infer the progress of the
+    // merge process.
+    // This is non-zero when |state| == MERGING or MERGE_COMPLETED.
+    uint64 sectors_allocated = 7;
+
+    // Metadata sectors allocated for the COW device. Recording this value right
+    // before the update and before the merge allows us to infer the progress of
+    // the merge process.
+    // This is non-zero when |state| == MERGING or MERGE_COMPLETED.
+    uint64 metadata_sectors = 8;
+}
diff --git a/fs_mgr/libsnapshot/device_info.cpp b/fs_mgr/libsnapshot/device_info.cpp
new file mode 100644
index 0000000..bacb41c
--- /dev/null
+++ b/fs_mgr/libsnapshot/device_info.cpp
@@ -0,0 +1,123 @@
+// 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 "device_info.h"
+
+#include <android-base/logging.h>
+#include <fs_mgr.h>
+#include <fs_mgr_overlayfs.h>
+
+namespace android {
+namespace snapshot {
+
+#ifdef LIBSNAPSHOT_USE_HAL
+using android::hardware::boot::V1_0::CommandResult;
+#endif
+
+using namespace std::string_literals;
+
+#ifdef __ANDROID_RECOVERY__
+constexpr bool kIsRecovery = true;
+#else
+constexpr bool kIsRecovery = false;
+#endif
+
+std::string DeviceInfo::GetGsidDir() const {
+    return "ota"s;
+}
+
+std::string DeviceInfo::GetMetadataDir() const {
+    return "/metadata/ota"s;
+}
+
+std::string DeviceInfo::GetSlotSuffix() const {
+    return fs_mgr_get_slot_suffix();
+}
+
+std::string DeviceInfo::GetOtherSlotSuffix() const {
+    return fs_mgr_get_other_slot_suffix();
+}
+
+const android::fs_mgr::IPartitionOpener& DeviceInfo::GetPartitionOpener() const {
+    return opener_;
+}
+
+std::string DeviceInfo::GetSuperDevice(uint32_t slot) const {
+    return fs_mgr_get_super_partition_name(slot);
+}
+
+bool DeviceInfo::IsOverlayfsSetup() const {
+    return fs_mgr_overlayfs_is_setup();
+}
+
+#ifdef LIBSNAPSHOT_USE_HAL
+bool DeviceInfo::EnsureBootHal() {
+    if (!boot_control_) {
+        auto hal = android::hardware::boot::V1_0::IBootControl::getService();
+        if (!hal) {
+            LOG(ERROR) << "Could not find IBootControl HAL";
+            return false;
+        }
+        boot_control_ = android::hardware::boot::V1_1::IBootControl::castFrom(hal);
+        if (!boot_control_) {
+            LOG(ERROR) << "Could not find IBootControl 1.1 HAL";
+            return false;
+        }
+    }
+    return true;
+}
+#endif
+
+bool DeviceInfo::SetBootControlMergeStatus([[maybe_unused]] MergeStatus status) {
+#ifdef LIBSNAPSHOT_USE_HAL
+    if (!EnsureBootHal()) {
+        return false;
+    }
+    if (!boot_control_->setSnapshotMergeStatus(status)) {
+        LOG(ERROR) << "Unable to set the snapshot merge status";
+        return false;
+    }
+    return true;
+#else
+    LOG(ERROR) << "HAL support not enabled.";
+    return false;
+#endif
+}
+
+bool DeviceInfo::IsRecovery() const {
+    return kIsRecovery;
+}
+
+bool DeviceInfo::SetSlotAsUnbootable([[maybe_unused]] unsigned int slot) {
+#ifdef LIBSNAPSHOT_USE_HAL
+    if (!EnsureBootHal()) {
+        return false;
+    }
+
+    CommandResult result = {};
+    auto cb = [&](CommandResult r) -> void { result = r; };
+    boot_control_->setSlotAsUnbootable(slot, cb);
+    if (!result.success) {
+        LOG(ERROR) << "Error setting slot " << slot << " unbootable: " << result.errMsg;
+        return false;
+    }
+    return true;
+#else
+    LOG(ERROR) << "HAL support not enabled.";
+    return false;
+#endif
+}
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/device_info.h b/fs_mgr/libsnapshot/device_info.h
new file mode 100644
index 0000000..d8d3d91
--- /dev/null
+++ b/fs_mgr/libsnapshot/device_info.h
@@ -0,0 +1,53 @@
+// 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 <string>
+
+#ifdef LIBSNAPSHOT_USE_HAL
+#include <android/hardware/boot/1.1/IBootControl.h>
+#endif
+#include <liblp/partition_opener.h>
+#include <libsnapshot/snapshot.h>
+
+namespace android {
+namespace snapshot {
+
+class DeviceInfo final : public SnapshotManager::IDeviceInfo {
+    using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
+
+  public:
+    std::string GetGsidDir() const override;
+    std::string GetMetadataDir() const override;
+    std::string GetSlotSuffix() const override;
+    std::string GetOtherSlotSuffix() const override;
+    const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override;
+    std::string GetSuperDevice(uint32_t slot) const override;
+    bool IsOverlayfsSetup() const override;
+    bool SetBootControlMergeStatus(MergeStatus status) override;
+    bool SetSlotAsUnbootable(unsigned int slot) override;
+    bool IsRecovery() const override;
+
+  private:
+    bool EnsureBootHal();
+
+    android::fs_mgr::PartitionOpener opener_;
+#ifdef LIBSNAPSHOT_USE_HAL
+    android::sp<android::hardware::boot::V1_1::IBootControl> boot_control_;
+#endif
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/dm_snapshot_internals.h b/fs_mgr/libsnapshot/dm_snapshot_internals.h
new file mode 100644
index 0000000..fef256d
--- /dev/null
+++ b/fs_mgr/libsnapshot/dm_snapshot_internals.h
@@ -0,0 +1,135 @@
+// 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 <stdint.h>
+
+#include <vector>
+
+namespace android {
+namespace snapshot {
+
+class DmSnapCowSizeCalculator {
+  public:
+    DmSnapCowSizeCalculator(unsigned int sector_bytes, unsigned int chunk_sectors)
+        : sector_bytes_(sector_bytes),
+          chunk_sectors_(chunk_sectors),
+          exceptions_per_chunk(chunk_sectors_ * sector_bytes_ / (64 * 2 / 8)) {}
+
+    void WriteByte(uint64_t address) { WriteSector(address / sector_bytes_); }
+    void WriteSector(uint64_t sector) { WriteChunk(sector / chunk_sectors_); }
+    void WriteChunk(uint64_t chunk_id) {
+        if (modified_chunks_.size() <= chunk_id) {
+            modified_chunks_.resize(chunk_id + 1, false);
+        }
+        modified_chunks_[chunk_id] = true;
+    }
+
+    uint64_t cow_size_bytes() const { return cow_size_sectors() * sector_bytes_; }
+    uint64_t cow_size_sectors() const { return cow_size_chunks() * chunk_sectors_; }
+
+    /*
+     * The COW device has a precise internal structure as follows:
+     *
+     * - header (1 chunk)
+     * - #0 map and chunks
+     *   - map (1 chunk)
+     *   - chunks addressable by previous map (exceptions_per_chunk)
+     * - #1 map and chunks
+     *   - map (1 chunk)
+     *   - chunks addressable by previous map (exceptions_per_chunk)
+     * ...
+     * - #n: map and chunks
+     *   - map (1 chunk)
+     *   - chunks addressable by previous map (exceptions_per_chunk)
+     * - 1 extra chunk
+     */
+    uint64_t cow_size_chunks() const {
+        uint64_t modified_chunks_count = 0;
+        uint64_t cow_chunks = 0;
+
+        for (const auto& c : modified_chunks_) {
+            if (c) {
+                ++modified_chunks_count;
+            }
+        }
+
+        /* disk header + padding = 1 chunk */
+        cow_chunks += 1;
+
+        /* snapshot modified chunks */
+        cow_chunks += modified_chunks_count;
+
+        /* snapshot chunks index metadata */
+        cow_chunks += 1 + modified_chunks_count / exceptions_per_chunk;
+
+        return cow_chunks;
+    }
+
+  private:
+    /*
+     * Size of each sector in bytes.
+     */
+    const uint64_t sector_bytes_;
+
+    /*
+     * Size of each chunk in sectors.
+     */
+    const uint64_t chunk_sectors_;
+
+    /*
+     * The COW device stores tables to map the modified chunks. Each table
+     * has the size of exactly 1 chunk.
+     * Each row of the table (also called exception in the kernel) contains two
+     * 64 bit indices to identify the corresponding chunk, and this 128 bit row
+     * size is a constant.
+     * The number of exceptions that each table can contain determines the
+     * number of data chunks that separate two consecutive tables. This value
+     * is then fundamental to compute the space overhead introduced by the
+     * tables in COW devices.
+     */
+    const uint64_t exceptions_per_chunk;
+
+    /*
+     * |modified_chunks_| is a container that keeps trace of the modified
+     * chunks.
+     * Multiple options were considered when choosing the most appropriate data
+     * structure for this container. Here follows a summary of why vector<bool>
+     * has been chosen, taking as a reference a snapshot partition of 4 GiB and
+     * chunk size of 4 KiB.
+     * - std::set<uint64_t> is very space-efficient for a small number of
+     *   operations, but if the whole snapshot is changed, it would need to
+     *   store
+     *     4 GiB / 4 KiB * (64 bit / 8) = 8 MiB
+     *   just for the data, plus the additional data overhead for the red-black
+     *   tree used for data sorting (if each rb-tree element stores 3 address
+     *   and the word-aligne color, the total size grows to 32 MiB).
+     * - std::bitset<N> is not a good fit because requires a priori knowledge,
+     *   at compile time, of the bitset size.
+     * - std::vector<bool> is a special case of vector, which uses a data
+     *   compression that allows reducing the space utilization of each element
+     *   to 1 bit. In detail, this data structure is composed of a resizable
+     *   array of words, each of them representing a bitmap. On a 64 bit
+     *   device, modifying the whole 4 GiB snapshot grows this container up to
+     *     4 * GiB / 4 KiB / 64 = 64 KiB
+     *   that, even if is the same space requirement to change a single byte at
+     *   the highest address of the snapshot, is a very affordable space
+     *   requirement.
+     */
+    std::vector<bool> modified_chunks_;
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/auto_device.h b/fs_mgr/libsnapshot/include/libsnapshot/auto_device.h
new file mode 100644
index 0000000..73450db
--- /dev/null
+++ b/fs_mgr/libsnapshot/include/libsnapshot/auto_device.h
@@ -0,0 +1,42 @@
+// 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 <string>
+
+#include <android-base/macros.h>
+
+namespace android {
+namespace snapshot {
+
+// An abstract "device" that will be cleaned up (unmapped, unmounted, etc.) upon
+// destruction.
+struct AutoDevice {
+    virtual ~AutoDevice(){};
+    void Release();
+
+    bool HasDevice() const { return !name_.empty(); }
+
+  protected:
+    AutoDevice(const std::string& name) : name_(name) {}
+    std::string name_;
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(AutoDevice);
+    AutoDevice(AutoDevice&& other) = delete;
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
new file mode 100644
index 0000000..445e6db
--- /dev/null
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -0,0 +1,523 @@
+// 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 <stdint.h>
+
+#include <chrono>
+#include <map>
+#include <memory>
+#include <optional>
+#include <ostream>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+#include <fs_mgr_dm_linear.h>
+#include <libdm/dm.h>
+#include <libfiemap/image_manager.h>
+#include <liblp/builder.h>
+#include <liblp/liblp.h>
+#include <update_engine/update_metadata.pb.h>
+
+#include <libsnapshot/auto_device.h>
+
+#ifndef FRIEND_TEST
+#define FRIEND_TEST(test_set_name, individual_test) \
+    friend class test_set_name##_##individual_test##_Test
+#define DEFINED_FRIEND_TEST
+#endif
+
+namespace android {
+
+namespace fiemap {
+class IImageManager;
+}  // namespace fiemap
+
+namespace fs_mgr {
+struct CreateLogicalPartitionParams;
+class IPartitionOpener;
+}  // namespace fs_mgr
+
+// Forward declare IBootControl types since we cannot include only the headers
+// with Soong. Note: keep the enum width in sync.
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+enum class MergeStatus : int32_t;
+}  // namespace V1_1
+}  // namespace boot
+}  // namespace hardware
+
+namespace snapshot {
+
+struct AutoDeleteCowImage;
+struct AutoDeleteSnapshot;
+struct AutoDeviceList;
+struct PartitionCowCreator;
+class SnapshotStatus;
+
+static constexpr const std::string_view kCowGroupName = "cow";
+
+bool SourceCopyOperationIsClone(const chromeos_update_engine::InstallOperation& operation);
+
+enum class UpdateState : unsigned int {
+    // No update or merge is in progress.
+    None,
+
+    // An update is applying; snapshots may already exist.
+    Initiated,
+
+    // An update is pending, but has not been successfully booted yet.
+    Unverified,
+
+    // The kernel is merging in the background.
+    Merging,
+
+    // Post-merge cleanup steps could not be completed due to a transient
+    // error, but the next reboot will finish any pending operations.
+    MergeNeedsReboot,
+
+    // Merging is complete, and needs to be acknowledged.
+    MergeCompleted,
+
+    // Merging failed due to an unrecoverable error.
+    MergeFailed,
+
+    // The update was implicitly cancelled, either by a rollback or a flash
+    // operation via fastboot. This state can only be returned by WaitForMerge.
+    Cancelled
+};
+std::ostream& operator<<(std::ostream& os, UpdateState state);
+
+class SnapshotManager final {
+    using CreateLogicalPartitionParams = android::fs_mgr::CreateLogicalPartitionParams;
+    using IPartitionOpener = android::fs_mgr::IPartitionOpener;
+    using LpMetadata = android::fs_mgr::LpMetadata;
+    using MetadataBuilder = android::fs_mgr::MetadataBuilder;
+    using DeltaArchiveManifest = chromeos_update_engine::DeltaArchiveManifest;
+    using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
+
+  public:
+    // Dependency injection for testing.
+    class IDeviceInfo {
+      public:
+        virtual ~IDeviceInfo() {}
+        virtual std::string GetGsidDir() const = 0;
+        virtual std::string GetMetadataDir() const = 0;
+        virtual std::string GetSlotSuffix() const = 0;
+        virtual std::string GetOtherSlotSuffix() const = 0;
+        virtual std::string GetSuperDevice(uint32_t slot) const = 0;
+        virtual const IPartitionOpener& GetPartitionOpener() const = 0;
+        virtual bool IsOverlayfsSetup() const = 0;
+        virtual bool SetBootControlMergeStatus(MergeStatus status) = 0;
+        virtual bool SetSlotAsUnbootable(unsigned int slot) = 0;
+        virtual bool IsRecovery() const = 0;
+    };
+
+    ~SnapshotManager();
+
+    // Return a new SnapshotManager instance, or null on error. The device
+    // pointer is owned for the lifetime of SnapshotManager. If null, a default
+    // instance will be created.
+    static std::unique_ptr<SnapshotManager> New(IDeviceInfo* device = nullptr);
+
+    // This is similar to New(), except designed specifically for first-stage
+    // init or recovery.
+    static std::unique_ptr<SnapshotManager> NewForFirstStageMount(IDeviceInfo* device = nullptr);
+
+    // Helper function for first-stage init to check whether a SnapshotManager
+    // might be needed to perform first-stage mounts.
+    static bool IsSnapshotManagerNeeded();
+
+    // Begin an update. This must be called before creating any snapshots. It
+    // will fail if GetUpdateState() != None.
+    bool BeginUpdate();
+
+    // Cancel an update; any snapshots will be deleted. This is allowed if the
+    // state == Initiated, None, or Unverified (before rebooting to the new
+    // slot).
+    bool CancelUpdate();
+
+    // Mark snapshot writes as having completed. After this, new snapshots cannot
+    // be created, and the device must either cancel the OTA (either before
+    // rebooting or after rolling back), or merge the OTA.
+    // Before calling this function, all snapshots must be mapped.
+    bool FinishedSnapshotWrites();
+
+  private:
+    // Initiate a merge on all snapshot devices. This should only be used after an
+    // update has been marked successful after booting.
+    bool InitiateMerge();
+
+    // Perform any necessary post-boot actions. This should be run soon after
+    // /data is mounted.
+    //
+    // If a merge is in progress, this function will block until the merge is
+    // completed. If a merge or update was cancelled, this will clean up any
+    // update artifacts and return.
+    //
+    // Note that after calling this, GetUpdateState() may still return that a
+    // merge is in progress:
+    //   MergeFailed indicates that a fatal error occurred. WaitForMerge() may
+    //   called any number of times again to attempt to make more progress, but
+    //   we do not expect it to succeed if a catastrophic error occurred.
+    //
+    //   MergeNeedsReboot indicates that the merge has completed, but cleanup
+    //   failed. This can happen if for some reason resources were not closed
+    //   properly. In this case another reboot is needed before we can take
+    //   another OTA. However, WaitForMerge() can be called again without
+    //   rebooting, to attempt to finish cleanup anyway.
+    //
+    //   MergeCompleted indicates that the update has fully completed.
+    //   GetUpdateState will return None, and a new update can begin.
+    //
+    // The optional callback allows the caller to periodically check the
+    // progress with GetUpdateState().
+    UpdateState ProcessUpdateState(const std::function<void()>& callback = {});
+
+  public:
+    // Initiate the merge if necessary, then wait for the merge to finish.
+    // See InitiateMerge() and ProcessUpdateState() for details.
+    // Returns:
+    //   - None if no merge to initiate
+    //   - MergeCompleted if merge is completed
+    //   - other states indicating an error has occurred
+    UpdateState InitiateMergeAndWait();
+
+    // Wait for the merge if rebooted into the new slot. Does NOT initiate a
+    // merge. If the merge has not been initiated (but should be), wait.
+    // Returns:
+    //   - true there is no merge or merge finishes
+    //   - false indicating an error has occurred
+    bool WaitForMerge();
+
+    // Find the status of the current update, if any.
+    //
+    // |progress| depends on the returned status:
+    //   Merging: Value in the range [0, 100]
+    //   MergeCompleted: 100
+    //   Other: 0
+    UpdateState GetUpdateState(double* progress = nullptr);
+
+    // Create necessary COW device / files for OTA clients. New logical partitions will be added to
+    // group "cow" in target_metadata. Regions of partitions of current_metadata will be
+    // "write-protected" and snapshotted.
+    bool CreateUpdateSnapshots(const DeltaArchiveManifest& manifest);
+
+    // Map a snapshotted partition for OTA clients to write to. Write-protected regions are
+    // determined previously in CreateSnapshots.
+    bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, std::string* snapshot_path);
+
+    // Unmap a snapshot device that's previously mapped with MapUpdateSnapshot.
+    bool UnmapUpdateSnapshot(const std::string& target_partition_name);
+
+    // If this returns true, first-stage mount must call
+    // CreateLogicalAndSnapshotPartitions rather than CreateLogicalPartitions.
+    bool NeedSnapshotsInFirstStageMount();
+
+    // Perform first-stage mapping of snapshot targets. This replaces init's
+    // call to CreateLogicalPartitions when snapshots are present.
+    bool CreateLogicalAndSnapshotPartitions(const std::string& super_device);
+
+    // This method should be called preceding any wipe or flash of metadata or
+    // userdata. It is only valid in recovery or fastbootd, and it ensures that
+    // a merge has been completed.
+    //
+    // When userdata will be wiped or flashed, it is necessary to clean up any
+    // snapshot state. If a merge is in progress, the merge must be finished.
+    // If a snapshot is present but not yet merged, the slot must be marked as
+    // unbootable.
+    //
+    // Returns true on success (or nothing to do), false on failure. The
+    // optional callback fires periodically to query progress via GetUpdateState.
+    bool HandleImminentDataWipe(const std::function<void()>& callback = {});
+
+    // Dump debug information.
+    bool Dump(std::ostream& os);
+
+    // Ensure metadata directory is mounted in recovery. When the returned
+    // AutoDevice is destroyed, the metadata directory is automatically
+    // unmounted.
+    // Return nullptr if any failure.
+    // In Android mode, Return an AutoDevice that does nothing
+    // In recovery, return an AutoDevice that does nothing if metadata entry
+    // is not found in fstab.
+    // Note: if this function is called the second time before the AutoDevice returned from the
+    // first call is destroyed, the device will be unmounted when any of these AutoDevices is
+    // destroyed. For example:
+    //   auto a = mgr->EnsureMetadataMounted(); // mounts
+    //   auto b = mgr->EnsureMetadataMounted(); // does nothing
+    //   b.reset() // unmounts
+    //   a.reset() // does nothing
+    std::unique_ptr<AutoDevice> EnsureMetadataMounted();
+
+  private:
+    FRIEND_TEST(SnapshotTest, CleanFirstStageMount);
+    FRIEND_TEST(SnapshotTest, CreateSnapshot);
+    FRIEND_TEST(SnapshotTest, FirstStageMountAfterRollback);
+    FRIEND_TEST(SnapshotTest, FirstStageMountAndMerge);
+    FRIEND_TEST(SnapshotTest, FlashSuperDuringMerge);
+    FRIEND_TEST(SnapshotTest, FlashSuperDuringUpdate);
+    FRIEND_TEST(SnapshotTest, MapPartialSnapshot);
+    FRIEND_TEST(SnapshotTest, MapSnapshot);
+    FRIEND_TEST(SnapshotTest, Merge);
+    FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot);
+    FRIEND_TEST(SnapshotTest, UpdateBootControlHal);
+    FRIEND_TEST(SnapshotUpdateTest, DataWipeAfterRollback);
+    FRIEND_TEST(SnapshotUpdateTest, DataWipeRollbackInRecovery);
+    FRIEND_TEST(SnapshotUpdateTest, MergeCannotRemoveCow);
+    FRIEND_TEST(SnapshotUpdateTest, MergeInRecovery);
+    FRIEND_TEST(SnapshotUpdateTest, SnapshotStatusFileWithoutCow);
+    friend class SnapshotTest;
+    friend class SnapshotUpdateTest;
+    friend class FlashAfterUpdateTest;
+    friend class LockTestConsumer;
+    friend struct AutoDeleteCowImage;
+    friend struct AutoDeleteSnapshot;
+    friend struct PartitionCowCreator;
+
+    using DmTargetSnapshot = android::dm::DmTargetSnapshot;
+    using IImageManager = android::fiemap::IImageManager;
+    using TargetInfo = android::dm::DeviceMapper::TargetInfo;
+
+    explicit SnapshotManager(IDeviceInfo* info);
+
+    // This is created lazily since it can connect via binder.
+    bool EnsureImageManager();
+
+    // Helper for first-stage init.
+    bool ForceLocalImageManager();
+
+    // Helper function for tests.
+    IImageManager* image_manager() const { return images_.get(); }
+
+    // Since libsnapshot is included into multiple processes, we flock() our
+    // files for simple synchronization. LockedFile is a helper to assist with
+    // this. It also serves as a proof-of-lock for some functions.
+    class LockedFile final {
+      public:
+        LockedFile(const std::string& path, android::base::unique_fd&& fd, int lock_mode)
+            : path_(path), fd_(std::move(fd)), lock_mode_(lock_mode) {}
+        ~LockedFile();
+        int lock_mode() const { return lock_mode_; }
+
+      private:
+        std::string path_;
+        android::base::unique_fd fd_;
+        int lock_mode_;
+    };
+    static std::unique_ptr<LockedFile> OpenFile(const std::string& file, int lock_flags);
+
+    // Create a new snapshot record. This creates the backing COW store and
+    // persists information needed to map the device. The device can be mapped
+    // with MapSnapshot().
+    //
+    // |status|.device_size should be the size of the base_device that will be passed
+    // via MapDevice(). |status|.snapshot_size should be the number of bytes in the
+    // base device, starting from 0, that will be snapshotted. |status|.cow_file_size
+    // should be the amount of space that will be allocated to store snapshot
+    // deltas.
+    //
+    // If |status|.snapshot_size < |status|.device_size, then the device will always
+    // be mapped with two table entries: a dm-snapshot range covering
+    // snapshot_size, and a dm-linear range covering the remainder.
+    //
+    // All sizes are specified in bytes, and the device, snapshot, COW partition and COW file sizes
+    // must be a multiple of the sector size (512 bytes).
+    bool CreateSnapshot(LockedFile* lock, SnapshotStatus* status);
+
+    // |name| should be the base partition name (e.g. "system_a"). Create the
+    // backing COW image using the size previously passed to CreateSnapshot().
+    bool CreateCowImage(LockedFile* lock, const std::string& name);
+
+    // Map a snapshot device that was previously created with CreateSnapshot.
+    // If a merge was previously initiated, the device-mapper table will have a
+    // snapshot-merge target instead of a snapshot target. If the timeout
+    // parameter greater than zero, this function will wait the given amount
+    // of time for |dev_path| to become available, and fail otherwise. If
+    // timeout_ms is 0, then no wait will occur and |dev_path| may not yet
+    // exist on return.
+    bool MapSnapshot(LockedFile* lock, const std::string& name, const std::string& base_device,
+                     const std::string& cow_device, const std::chrono::milliseconds& timeout_ms,
+                     std::string* dev_path);
+
+    // Map a COW image that was previous created with CreateCowImage.
+    std::optional<std::string> MapCowImage(const std::string& name,
+                                           const std::chrono::milliseconds& timeout_ms);
+
+    // Remove the backing copy-on-write image and snapshot states for the named snapshot. The
+    // caller is responsible for ensuring that the snapshot is unmapped.
+    bool DeleteSnapshot(LockedFile* lock, const std::string& name);
+
+    // Unmap a snapshot device previously mapped with MapSnapshotDevice().
+    bool UnmapSnapshot(LockedFile* lock, const std::string& name);
+
+    // Unmap a COW image device previously mapped with MapCowImage().
+    bool UnmapCowImage(const std::string& name);
+
+    // Unmap and remove all known snapshots.
+    bool RemoveAllSnapshots(LockedFile* lock);
+
+    // List the known snapshot names.
+    bool ListSnapshots(LockedFile* lock, std::vector<std::string>* snapshots);
+
+    // Check for a cancelled or rolled back merge, returning true if such a
+    // condition was detected and handled.
+    bool HandleCancelledUpdate(LockedFile* lock);
+
+    // Helper for HandleCancelledUpdate. Assumes booting from new slot.
+    bool HandleCancelledUpdateOnNewSlot(LockedFile* lock);
+
+    // Remove artifacts created by the update process, such as snapshots, and
+    // set the update state to None.
+    bool RemoveAllUpdateState(LockedFile* lock);
+
+    // Interact with /metadata/ota.
+    std::unique_ptr<LockedFile> OpenLock(int lock_flags);
+    std::unique_ptr<LockedFile> LockShared();
+    std::unique_ptr<LockedFile> LockExclusive();
+    std::string GetLockPath() const;
+
+    // Interact with /metadata/ota/state.
+    UpdateState ReadUpdateState(LockedFile* file);
+    bool WriteUpdateState(LockedFile* file, UpdateState state);
+    std::string GetStateFilePath() const;
+
+    // Helpers for merging.
+    bool SwitchSnapshotToMerge(LockedFile* lock, const std::string& name);
+    bool RewriteSnapshotDeviceTable(const std::string& dm_name);
+    bool MarkSnapshotMergeCompleted(LockedFile* snapshot_lock, const std::string& snapshot_name);
+    void AcknowledgeMergeSuccess(LockedFile* lock);
+    void AcknowledgeMergeFailure();
+    std::unique_ptr<LpMetadata> ReadCurrentMetadata();
+
+    enum class MetadataPartitionState {
+        // Partition does not exist.
+        None,
+        // Partition is flashed.
+        Flashed,
+        // Partition is created by OTA client.
+        Updated,
+    };
+    // Helper function to check the state of a partition as described in metadata.
+    MetadataPartitionState GetMetadataPartitionState(const LpMetadata& metadata,
+                                                     const std::string& name);
+
+    // Note that these require the name of the device containing the snapshot,
+    // which may be the "inner" device. Use GetsnapshotDeviecName().
+    bool QuerySnapshotStatus(const std::string& dm_name, std::string* target_type,
+                             DmTargetSnapshot::Status* status);
+    bool IsSnapshotDevice(const std::string& dm_name, TargetInfo* target = nullptr);
+
+    // Internal callback for when merging is complete.
+    bool OnSnapshotMergeComplete(LockedFile* lock, const std::string& name,
+                                 const SnapshotStatus& status);
+    bool CollapseSnapshotDevice(const std::string& name, const SnapshotStatus& status);
+
+    // Only the following UpdateStates are used here:
+    //   UpdateState::Merging
+    //   UpdateState::MergeCompleted
+    //   UpdateState::MergeFailed
+    //   UpdateState::MergeNeedsReboot
+    UpdateState CheckMergeState();
+    UpdateState CheckMergeState(LockedFile* lock);
+    UpdateState CheckTargetMergeState(LockedFile* lock, const std::string& name);
+
+    // Interact with status files under /metadata/ota/snapshots.
+    bool WriteSnapshotStatus(LockedFile* lock, const SnapshotStatus& status);
+    bool ReadSnapshotStatus(LockedFile* lock, const std::string& name, SnapshotStatus* status);
+    std::string GetSnapshotStatusFilePath(const std::string& name);
+
+    std::string GetSnapshotBootIndicatorPath();
+    void RemoveSnapshotBootIndicator();
+
+    // Return the name of the device holding the "snapshot" or "snapshot-merge"
+    // target. This may not be the final device presented via MapSnapshot(), if
+    // for example there is a linear segment.
+    std::string GetSnapshotDeviceName(const std::string& snapshot_name,
+                                      const SnapshotStatus& status);
+
+    // Map the base device, COW devices, and snapshot device.
+    bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params,
+                                  std::string* path);
+
+    // Map the COW devices, including the partition in super and the images.
+    // |params|:
+    //    - |partition_name| should be the name of the top-level partition (e.g. system_b),
+    //            not system_b-cow-img
+    //    - |device_name| and |partition| is ignored
+    //    - |timeout_ms| and the rest is respected
+    // Return the path in |cow_device_path| (e.g. /dev/block/dm-1) and major:minor in
+    // |cow_device_string|
+    bool MapCowDevices(LockedFile* lock, const CreateLogicalPartitionParams& params,
+                       const SnapshotStatus& snapshot_status, AutoDeviceList* created_devices,
+                       std::string* cow_name);
+
+    // The reverse of MapCowDevices.
+    bool UnmapCowDevices(LockedFile* lock, const std::string& name);
+
+    // The reverse of MapPartitionWithSnapshot.
+    bool UnmapPartitionWithSnapshot(LockedFile* lock, const std::string& target_partition_name);
+
+    // If there isn't a previous update, return true. |needs_merge| is set to false.
+    // If there is a previous update but the device has not boot into it, tries to cancel the
+    //   update and delete any snapshots. Return true if successful. |needs_merge| is set to false.
+    // If there is a previous update and the device has boot into it, do nothing and return true.
+    //   |needs_merge| is set to true.
+    bool TryCancelUpdate(bool* needs_merge);
+
+    // Helper for CreateUpdateSnapshots.
+    // Creates all underlying images, COW partitions and snapshot files. Does not initialize them.
+    bool CreateUpdateSnapshotsInternal(LockedFile* lock, const DeltaArchiveManifest& manifest,
+                                       PartitionCowCreator* cow_creator,
+                                       AutoDeviceList* created_devices,
+                                       std::map<std::string, SnapshotStatus>* all_snapshot_status);
+
+    // Initialize snapshots so that they can be mapped later.
+    // Map the COW partition and zero-initialize the header.
+    bool InitializeUpdateSnapshots(
+            LockedFile* lock, MetadataBuilder* target_metadata,
+            const LpMetadata* exported_target_metadata, const std::string& target_suffix,
+            const std::map<std::string, SnapshotStatus>& all_snapshot_status);
+
+    // Unmap all partitions that were mapped by CreateLogicalAndSnapshotPartitions.
+    // This should only be called in recovery.
+    bool UnmapAllPartitions();
+
+    // Sanity check no snapshot overflows. Note that this returns false negatives if the snapshot
+    // overflows, then is remapped and not written afterwards. Hence, the function may only serve
+    // as a sanity check.
+    bool EnsureNoOverflowSnapshot(LockedFile* lock);
+
+    enum class Slot { Unknown, Source, Target };
+    friend std::ostream& operator<<(std::ostream& os, SnapshotManager::Slot slot);
+    Slot GetCurrentSlot();
+
+    std::string gsid_dir_;
+    std::string metadata_dir_;
+    std::unique_ptr<IDeviceInfo> device_;
+    std::unique_ptr<IImageManager> images_;
+    bool has_local_image_manager_ = false;
+};
+
+}  // namespace snapshot
+}  // namespace android
+
+#ifdef DEFINED_FRIEND_TEST
+#undef DEFINED_FRIEND_TEST
+#undef FRIEND_TEST
+#endif
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
new file mode 100644
index 0000000..2bf1b57
--- /dev/null
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -0,0 +1,159 @@
+// 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 <optional>
+#include <string>
+#include <unordered_set>
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <libfiemap/image_manager.h>
+#include <liblp/mock_property_fetcher.h>
+#include <liblp/partition_opener.h>
+#include <libsnapshot/snapshot.h>
+#include <storage_literals/storage_literals.h>
+#include <update_engine/update_metadata.pb.h>
+
+namespace android {
+namespace snapshot {
+
+using android::fs_mgr::IPropertyFetcher;
+using android::fs_mgr::MetadataBuilder;
+using android::fs_mgr::testing::MockPropertyFetcher;
+using android::hardware::boot::V1_1::MergeStatus;
+using chromeos_update_engine::DeltaArchiveManifest;
+using chromeos_update_engine::PartitionUpdate;
+using testing::_;
+using testing::AssertionResult;
+using testing::NiceMock;
+using testing::Return;
+
+using namespace android::storage_literals;
+using namespace std::string_literals;
+
+// These are not reset between each test because it's expensive to create
+// these resources (starting+connecting to gsid, zero-filling images).
+extern std::unique_ptr<SnapshotManager> sm;
+extern class TestDeviceInfo* test_device;
+extern std::string fake_super;
+static constexpr uint64_t kSuperSize = 16_MiB + 4_KiB;
+static constexpr uint64_t kGroupSize = 16_MiB;
+
+// Redirect requests for "super" to our fake super partition.
+class TestPartitionOpener final : public android::fs_mgr::PartitionOpener {
+  public:
+    explicit TestPartitionOpener(const std::string& fake_super_path)
+        : fake_super_path_(fake_super_path) {}
+
+    android::base::unique_fd Open(const std::string& partition_name, int flags) const override;
+    bool GetInfo(const std::string& partition_name,
+                 android::fs_mgr::BlockDeviceInfo* info) const override;
+    std::string GetDeviceString(const std::string& partition_name) const override;
+
+  private:
+    std::string fake_super_path_;
+};
+
+class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
+  public:
+    TestDeviceInfo() {}
+    explicit TestDeviceInfo(const std::string& fake_super) { set_fake_super(fake_super); }
+    TestDeviceInfo(const std::string& fake_super, const std::string& slot_suffix)
+        : TestDeviceInfo(fake_super) {
+        set_slot_suffix(slot_suffix);
+    }
+    std::string GetGsidDir() const override { return "ota/test"s; }
+    std::string GetMetadataDir() const override { return "/metadata/ota/test"s; }
+    std::string GetSlotSuffix() const override { return slot_suffix_; }
+    std::string GetOtherSlotSuffix() const override { return slot_suffix_ == "_a" ? "_b" : "_a"; }
+    std::string GetSuperDevice([[maybe_unused]] uint32_t slot) const override { return "super"; }
+    const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
+        return *opener_.get();
+    }
+    bool SetBootControlMergeStatus(MergeStatus status) override {
+        merge_status_ = status;
+        return true;
+    }
+    bool IsOverlayfsSetup() const override { return false; }
+    bool IsRecovery() const override { return recovery_; }
+    bool SetSlotAsUnbootable(unsigned int slot) override {
+        unbootable_slots_.insert(slot);
+        return true;
+    }
+
+    bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; }
+
+    void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; }
+    void set_fake_super(const std::string& path) {
+        opener_ = std::make_unique<TestPartitionOpener>(path);
+    }
+    void set_recovery(bool value) { recovery_ = value; }
+    MergeStatus merge_status() const { return merge_status_; }
+
+  private:
+    std::string slot_suffix_ = "_a";
+    std::unique_ptr<TestPartitionOpener> opener_;
+    MergeStatus merge_status_;
+    bool recovery_ = false;
+    std::unordered_set<uint32_t> unbootable_slots_;
+};
+
+class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher {
+  public:
+    SnapshotTestPropertyFetcher(const std::string& slot_suffix) {
+        ON_CALL(*this, GetProperty("ro.boot.slot_suffix", _)).WillByDefault(Return(slot_suffix));
+        ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions", _))
+                .WillByDefault(Return(true));
+        ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+                .WillByDefault(Return(false));
+        ON_CALL(*this, GetBoolProperty("ro.virtual_ab.enabled", _)).WillByDefault(Return(true));
+    }
+
+    static void SetUp(const std::string& slot_suffix = "_a") { Reset(slot_suffix); }
+
+    static void TearDown() { Reset("_a"); }
+
+  private:
+    static void Reset(const std::string& slot_suffix) {
+        IPropertyFetcher::OverrideForTesting(
+                std::make_unique<NiceMock<SnapshotTestPropertyFetcher>>(slot_suffix));
+    }
+};
+
+// Helper for error-spam-free cleanup.
+void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::string& name);
+
+// Write some random data to the given device.
+// If expect_size is not specified, will write until reaching end of the device.
+// Expect space of |path| is multiple of 4K.
+bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size = std::nullopt,
+                     std::string* hash = nullptr);
+
+std::optional<std::string> GetHash(const std::string& path);
+
+// Add partitions and groups described by |manifest|.
+AssertionResult FillFakeMetadata(MetadataBuilder* builder, const DeltaArchiveManifest& manifest,
+                                 const std::string& suffix);
+
+// In the update package metadata, set a partition with the given size.
+void SetSize(PartitionUpdate* partition_update, uint64_t size);
+
+// Get partition size from update package metadata.
+uint64_t GetSize(PartitionUpdate* partition_update);
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.cpp b/fs_mgr/libsnapshot/partition_cow_creator.cpp
new file mode 100644
index 0000000..61f5c0c
--- /dev/null
+++ b/fs_mgr/libsnapshot/partition_cow_creator.cpp
@@ -0,0 +1,175 @@
+// 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 "partition_cow_creator.h"
+
+#include <math.h>
+
+#include <android-base/logging.h>
+#include <android/snapshot/snapshot.pb.h>
+
+#include "dm_snapshot_internals.h"
+#include "utility.h"
+
+using android::dm::kSectorSize;
+using android::fs_mgr::Extent;
+using android::fs_mgr::Interval;
+using android::fs_mgr::kDefaultBlockSize;
+using android::fs_mgr::Partition;
+using chromeos_update_engine::InstallOperation;
+template <typename T>
+using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>;
+
+namespace android {
+namespace snapshot {
+
+// Intersect two linear extents. If no intersection, return an extent with length 0.
+static std::unique_ptr<Extent> Intersect(Extent* target_extent, Extent* existing_extent) {
+    // Convert target_extent and existing_extent to linear extents. Zero extents
+    // doesn't matter and doesn't result in any intersection.
+    auto existing_linear_extent = existing_extent->AsLinearExtent();
+    if (!existing_linear_extent) return nullptr;
+
+    auto target_linear_extent = target_extent->AsLinearExtent();
+    if (!target_linear_extent) return nullptr;
+
+    return Interval::Intersect(target_linear_extent->AsInterval(),
+                               existing_linear_extent->AsInterval())
+            .AsExtent();
+}
+
+// Check that partition |p| contains |e| fully. Both of them should
+// be from |target_metadata|.
+// Returns true as long as |e| is a subrange of any extent of |p|.
+bool PartitionCowCreator::HasExtent(Partition* p, Extent* e) {
+    for (auto& partition_extent : p->extents()) {
+        auto intersection = Intersect(partition_extent.get(), e);
+        if (intersection != nullptr && intersection->num_sectors() == e->num_sectors()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool SourceCopyOperationIsClone(const InstallOperation& operation) {
+    using ChromeOSExtent = chromeos_update_engine::Extent;
+    if (operation.src_extents().size() != operation.dst_extents().size()) {
+        return false;
+    }
+    return std::equal(operation.src_extents().begin(), operation.src_extents().end(),
+                      operation.dst_extents().begin(),
+                      [](const ChromeOSExtent& src, const ChromeOSExtent& dst) {
+                          return src.start_block() == dst.start_block() &&
+                                 src.num_blocks() == dst.num_blocks();
+                      });
+}
+
+void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Extent& de,
+                 unsigned int sectors_per_block) {
+    const auto block_boundary = de.start_block() + de.num_blocks();
+    for (auto b = de.start_block(); b < block_boundary; ++b) {
+        for (unsigned int s = 0; s < sectors_per_block; ++s) {
+            const auto sector_id = b * sectors_per_block + s;
+            sc->WriteSector(sector_id);
+        }
+    }
+}
+
+uint64_t PartitionCowCreator::GetCowSize() {
+    // WARNING: The origin partition should be READ-ONLY
+    const uint64_t logical_block_size = current_metadata->logical_block_size();
+    const unsigned int sectors_per_block = logical_block_size / kSectorSize;
+    DmSnapCowSizeCalculator sc(kSectorSize, kSnapshotChunkSize);
+
+    // Allocate space for extra extents (if any). These extents are those that can be
+    // used for error corrections or to store verity hash trees.
+    for (const auto& de : extra_extents) {
+        WriteExtent(&sc, de, sectors_per_block);
+    }
+
+    if (operations == nullptr) return sc.cow_size_bytes();
+
+    for (const auto& iop : *operations) {
+        // Do not allocate space for operations that are going to be skipped
+        // during OTA application.
+        if (iop.type() == InstallOperation::SOURCE_COPY && SourceCopyOperationIsClone(iop))
+            continue;
+
+        for (const auto& de : iop.dst_extents()) {
+            WriteExtent(&sc, de, sectors_per_block);
+        }
+    }
+
+    return sc.cow_size_bytes();
+}
+
+std::optional<PartitionCowCreator::Return> PartitionCowCreator::Run() {
+    CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
+          target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME);
+
+    const uint64_t logical_block_size = current_metadata->logical_block_size();
+    CHECK(logical_block_size != 0 && !(logical_block_size & (logical_block_size - 1)))
+            << "logical_block_size is not power of 2";
+
+    Return ret;
+    ret.snapshot_status.set_name(target_partition->name());
+    ret.snapshot_status.set_device_size(target_partition->size());
+    ret.snapshot_status.set_snapshot_size(target_partition->size());
+
+    // Being the COW partition virtual, its size doesn't affect the storage
+    // memory that will be occupied by the target.
+    // The actual storage space is affected by the COW file, whose size depends
+    // on the chunks that diverged between |current| and |target|.
+    // If the |target| partition is bigger than |current|, the data that is
+    // modified outside of |current| can be written directly to |current|.
+    // This because the data that will be written outside of |current| would
+    // not invalidate any useful information of |current|, thus:
+    // - if the snapshot is accepted for merge, this data would be already at
+    // the right place and should not be copied;
+    // - in the unfortunate case of the snapshot to be discarded, the regions
+    // modified by this data can be set as free regions and reused.
+    // Compute regions that are free in both current and target metadata. These are the regions
+    // we can use for COW partition.
+    auto target_free_regions = target_metadata->GetFreeRegions();
+    auto current_free_regions = current_metadata->GetFreeRegions();
+    auto free_regions = Interval::Intersect(target_free_regions, current_free_regions);
+    uint64_t free_region_length = 0;
+    for (const auto& interval : free_regions) {
+        free_region_length += interval.length();
+    }
+    free_region_length *= kSectorSize;
+
+    LOG(INFO) << "Remaining free space for COW: " << free_region_length << " bytes";
+    auto cow_size = GetCowSize();
+
+    // Compute the COW partition size.
+    uint64_t cow_partition_size = std::min(cow_size, free_region_length);
+    // Round it down to the nearest logical block. Logical partitions must be a multiple
+    // of logical blocks.
+    cow_partition_size &= ~(logical_block_size - 1);
+    ret.snapshot_status.set_cow_partition_size(cow_partition_size);
+    // Assign cow_partition_usable_regions to indicate what regions should the COW partition uses.
+    ret.cow_partition_usable_regions = std::move(free_regions);
+
+    auto cow_file_size = cow_size - cow_partition_size;
+    // Round it up to the nearest sector.
+    cow_file_size += kSectorSize - 1;
+    cow_file_size &= ~(kSectorSize - 1);
+    ret.snapshot_status.set_cow_file_size(cow_file_size);
+
+    return ret;
+}
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.h b/fs_mgr/libsnapshot/partition_cow_creator.h
new file mode 100644
index 0000000..699f9a1
--- /dev/null
+++ b/fs_mgr/libsnapshot/partition_cow_creator.h
@@ -0,0 +1,72 @@
+// 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 <stdint.h>
+
+#include <optional>
+#include <string>
+#include <vector>
+
+#include <liblp/builder.h>
+#include <update_engine/update_metadata.pb.h>
+
+#include <android/snapshot/snapshot.pb.h>
+
+namespace android {
+namespace snapshot {
+
+// Helper class that creates COW for a partition.
+struct PartitionCowCreator {
+    using Extent = android::fs_mgr::Extent;
+    using ChromeOSExtent = chromeos_update_engine::Extent;
+    using Interval = android::fs_mgr::Interval;
+    using MetadataBuilder = android::fs_mgr::MetadataBuilder;
+    using Partition = android::fs_mgr::Partition;
+    using InstallOperation = chromeos_update_engine::InstallOperation;
+    template <typename T>
+    using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>;
+
+    // The metadata that will be written to target metadata slot.
+    MetadataBuilder* target_metadata = nullptr;
+    // The suffix of the target slot.
+    std::string target_suffix;
+    // The partition in target_metadata that needs to be snapshotted.
+    Partition* target_partition = nullptr;
+    // The metadata at the current slot (that would be used if the device boots
+    // normally). This is used to determine which extents are being used.
+    MetadataBuilder* current_metadata = nullptr;
+    // The suffix of the current slot.
+    std::string current_suffix;
+    // List of operations to be applied on the partition.
+    const RepeatedPtrField<InstallOperation>* operations = nullptr;
+    // Extra extents that are going to be invalidated during the update
+    // process.
+    std::vector<ChromeOSExtent> extra_extents = {};
+
+    struct Return {
+        SnapshotStatus snapshot_status;
+        std::vector<Interval> cow_partition_usable_regions;
+    };
+
+    std::optional<Return> Run();
+
+  private:
+    bool HasExtent(Partition* p, Extent* e);
+    uint64_t GetCowSize();
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
new file mode 100644
index 0000000..9da3f05
--- /dev/null
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -0,0 +1,217 @@
+// 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.
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <libdm/dm.h>
+#include <liblp/builder.h>
+#include <liblp/property_fetcher.h>
+
+#include <libsnapshot/test_helpers.h>
+
+#include "dm_snapshot_internals.h"
+#include "partition_cow_creator.h"
+#include "utility.h"
+
+using namespace android::fs_mgr;
+
+namespace android {
+namespace snapshot {
+
+class PartitionCowCreatorTest : public ::testing::Test {
+  public:
+    void SetUp() override { SnapshotTestPropertyFetcher::SetUp(); }
+    void TearDown() override { SnapshotTestPropertyFetcher::TearDown(); }
+};
+
+TEST_F(PartitionCowCreatorTest, IntersectSelf) {
+    constexpr uint64_t initial_size = 1_MiB;
+    constexpr uint64_t final_size = 40_KiB;
+
+    auto builder_a = MetadataBuilder::New(initial_size, 1_KiB, 2);
+    ASSERT_NE(builder_a, nullptr);
+    auto system_a = builder_a->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(system_a, nullptr);
+    ASSERT_TRUE(builder_a->ResizePartition(system_a, final_size));
+
+    auto builder_b = MetadataBuilder::New(initial_size, 1_KiB, 2);
+    ASSERT_NE(builder_b, nullptr);
+    auto system_b = builder_b->AddPartition("system_b", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(system_b, nullptr);
+    ASSERT_TRUE(builder_b->ResizePartition(system_b, final_size));
+
+    PartitionCowCreator creator{.target_metadata = builder_b.get(),
+                                .target_suffix = "_b",
+                                .target_partition = system_b,
+                                .current_metadata = builder_a.get(),
+                                .current_suffix = "_a"};
+    auto ret = creator.Run();
+    ASSERT_TRUE(ret.has_value());
+    ASSERT_EQ(final_size, ret->snapshot_status.device_size());
+    ASSERT_EQ(final_size, ret->snapshot_status.snapshot_size());
+}
+
+TEST_F(PartitionCowCreatorTest, Holes) {
+    const auto& opener = test_device->GetPartitionOpener();
+
+    constexpr auto slack_space = 1_MiB;
+    constexpr auto big_size = (kSuperSize - slack_space) / 2;
+    constexpr auto small_size = big_size / 2;
+
+    BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4_KiB);
+    std::vector<BlockDeviceInfo> devices = {super_device};
+    auto source = MetadataBuilder::New(devices, "super", 1_KiB, 2);
+    auto system = source->AddPartition("system_a", 0);
+    ASSERT_NE(nullptr, system);
+    ASSERT_TRUE(source->ResizePartition(system, big_size));
+    auto vendor = source->AddPartition("vendor_a", 0);
+    ASSERT_NE(nullptr, vendor);
+    ASSERT_TRUE(source->ResizePartition(vendor, big_size));
+    // Create a hole between system and vendor
+    ASSERT_TRUE(source->ResizePartition(system, small_size));
+    auto source_metadata = source->Export();
+    ASSERT_NE(nullptr, source_metadata);
+    ASSERT_TRUE(FlashPartitionTable(opener, fake_super, *source_metadata.get()));
+
+    auto target = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
+    // Shrink vendor
+    vendor = target->FindPartition("vendor_b");
+    ASSERT_NE(nullptr, vendor);
+    ASSERT_TRUE(target->ResizePartition(vendor, small_size));
+    // Grow system to take hole & saved space from vendor
+    system = target->FindPartition("system_b");
+    ASSERT_NE(nullptr, system);
+    ASSERT_TRUE(target->ResizePartition(system, big_size * 2 - small_size));
+
+    PartitionCowCreator creator{.target_metadata = target.get(),
+                                .target_suffix = "_b",
+                                .target_partition = system,
+                                .current_metadata = source.get(),
+                                .current_suffix = "_a"};
+    auto ret = creator.Run();
+    ASSERT_TRUE(ret.has_value());
+}
+
+TEST_F(PartitionCowCreatorTest, CowSize) {
+    using InstallOperation = chromeos_update_engine::InstallOperation;
+    using RepeatedInstallOperationPtr = google::protobuf::RepeatedPtrField<InstallOperation>;
+    using Extent = chromeos_update_engine::Extent;
+
+    constexpr uint64_t initial_size = 50_MiB;
+    constexpr uint64_t final_size = 40_MiB;
+
+    auto builder_a = MetadataBuilder::New(initial_size, 1_KiB, 2);
+    ASSERT_NE(builder_a, nullptr);
+    auto system_a = builder_a->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(system_a, nullptr);
+    ASSERT_TRUE(builder_a->ResizePartition(system_a, final_size));
+
+    auto builder_b = MetadataBuilder::New(initial_size, 1_KiB, 2);
+    ASSERT_NE(builder_b, nullptr);
+    auto system_b = builder_b->AddPartition("system_b", LP_PARTITION_ATTR_READONLY);
+    ASSERT_NE(system_b, nullptr);
+    ASSERT_TRUE(builder_b->ResizePartition(system_b, final_size));
+
+    const uint64_t block_size = builder_b->logical_block_size();
+    const uint64_t chunk_size = kSnapshotChunkSize * dm::kSectorSize;
+    ASSERT_EQ(chunk_size, block_size);
+
+    auto cow_device_size = [](const std::vector<InstallOperation>& iopv, MetadataBuilder* builder_a,
+                              MetadataBuilder* builder_b, Partition* system_b) {
+        RepeatedInstallOperationPtr riop(iopv.begin(), iopv.end());
+        PartitionCowCreator creator{.target_metadata = builder_b,
+                                    .target_suffix = "_b",
+                                    .target_partition = system_b,
+                                    .current_metadata = builder_a,
+                                    .current_suffix = "_a",
+                                    .operations = &riop};
+
+        auto ret = creator.Run();
+
+        if (ret.has_value()) {
+            return ret->snapshot_status.cow_file_size() + ret->snapshot_status.cow_partition_size();
+        }
+        return std::numeric_limits<uint64_t>::max();
+    };
+
+    std::vector<InstallOperation> iopv;
+    InstallOperation iop;
+    Extent* e;
+
+    // No data written, no operations performed
+    ASSERT_EQ(2 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+    // No data written
+    e = iop.add_dst_extents();
+    e->set_start_block(0);
+    e->set_num_blocks(0);
+    iopv.push_back(iop);
+    ASSERT_EQ(2 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+    e = iop.add_dst_extents();
+    e->set_start_block(1);
+    e->set_num_blocks(0);
+    iopv.push_back(iop);
+    ASSERT_EQ(2 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+    // Fill the first block
+    e = iop.add_dst_extents();
+    e->set_start_block(0);
+    e->set_num_blocks(1);
+    iopv.push_back(iop);
+    ASSERT_EQ(3 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+    // Fill the second block
+    e = iop.add_dst_extents();
+    e->set_start_block(1);
+    e->set_num_blocks(1);
+    iopv.push_back(iop);
+    ASSERT_EQ(4 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+
+    // Jump to 5th block and write 2
+    e = iop.add_dst_extents();
+    e->set_start_block(5);
+    e->set_num_blocks(2);
+    iopv.push_back(iop);
+    ASSERT_EQ(6 * chunk_size, cow_device_size(iopv, builder_a.get(), builder_b.get(), system_b));
+}
+
+TEST(DmSnapshotInternals, CowSizeCalculator) {
+    DmSnapCowSizeCalculator cc(512, 8);
+    unsigned long int b;
+
+    // Empty COW
+    ASSERT_EQ(cc.cow_size_sectors(), 16);
+
+    // First chunk written
+    for (b = 0; b < 4_KiB; ++b) {
+        cc.WriteByte(b);
+        ASSERT_EQ(cc.cow_size_sectors(), 24);
+    }
+
+    // Second chunk written
+    for (b = 4_KiB; b < 8_KiB; ++b) {
+        cc.WriteByte(b);
+        ASSERT_EQ(cc.cow_size_sectors(), 32);
+    }
+
+    // Leave a hole and write 5th chunk
+    for (b = 16_KiB; b < 20_KiB; ++b) {
+        cc.WriteByte(b);
+        ASSERT_EQ(cc.cow_size_sectors(), 40);
+    }
+}
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
new file mode 100644
index 0000000..a0ec068
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -0,0 +1,2360 @@
+// 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 <libsnapshot/snapshot.h>
+
+#include <dirent.h>
+#include <math.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/unistd.h>
+
+#include <optional>
+#include <thread>
+#include <unordered_set>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr.h>
+#include <fs_mgr_dm_linear.h>
+#include <fstab/fstab.h>
+#include <libdm/dm.h>
+#include <libfiemap/image_manager.h>
+#include <liblp/liblp.h>
+
+#include <android/snapshot/snapshot.pb.h>
+#include "device_info.h"
+#include "partition_cow_creator.h"
+#include "snapshot_metadata_updater.h"
+#include "utility.h"
+
+namespace android {
+namespace snapshot {
+
+using android::base::unique_fd;
+using android::dm::DeviceMapper;
+using android::dm::DmDeviceState;
+using android::dm::DmTable;
+using android::dm::DmTargetLinear;
+using android::dm::DmTargetSnapshot;
+using android::dm::kSectorSize;
+using android::dm::SnapshotStorageMode;
+using android::fiemap::IImageManager;
+using android::fs_mgr::CreateDmTable;
+using android::fs_mgr::CreateLogicalPartition;
+using android::fs_mgr::CreateLogicalPartitionParams;
+using android::fs_mgr::GetPartitionGroupName;
+using android::fs_mgr::GetPartitionName;
+using android::fs_mgr::LpMetadata;
+using android::fs_mgr::MetadataBuilder;
+using android::fs_mgr::SlotNumberForSlotSuffix;
+using android::hardware::boot::V1_1::MergeStatus;
+using chromeos_update_engine::DeltaArchiveManifest;
+using chromeos_update_engine::Extent;
+using chromeos_update_engine::InstallOperation;
+template <typename T>
+using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>;
+using std::chrono::duration_cast;
+using namespace std::chrono_literals;
+using namespace std::string_literals;
+
+static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
+static constexpr auto kUpdateStateCheckInterval = 2s;
+
+// Note: IImageManager is an incomplete type in the header, so the default
+// destructor doesn't work.
+SnapshotManager::~SnapshotManager() {}
+
+std::unique_ptr<SnapshotManager> SnapshotManager::New(IDeviceInfo* info) {
+    if (!info) {
+        info = new DeviceInfo();
+    }
+    return std::unique_ptr<SnapshotManager>(new SnapshotManager(info));
+}
+
+std::unique_ptr<SnapshotManager> SnapshotManager::NewForFirstStageMount(IDeviceInfo* info) {
+    auto sm = New(info);
+    if (!sm || !sm->ForceLocalImageManager()) {
+        return nullptr;
+    }
+    return sm;
+}
+
+SnapshotManager::SnapshotManager(IDeviceInfo* device) : device_(device) {
+    gsid_dir_ = device_->GetGsidDir();
+    metadata_dir_ = device_->GetMetadataDir();
+}
+
+static std::string GetCowName(const std::string& snapshot_name) {
+    return snapshot_name + "-cow";
+}
+
+static std::string GetCowImageDeviceName(const std::string& snapshot_name) {
+    return snapshot_name + "-cow-img";
+}
+
+static std::string GetBaseDeviceName(const std::string& partition_name) {
+    return partition_name + "-base";
+}
+
+static std::string GetSnapshotExtraDeviceName(const std::string& snapshot_name) {
+    return snapshot_name + "-inner";
+}
+
+bool SnapshotManager::BeginUpdate() {
+    bool needs_merge = false;
+    if (!TryCancelUpdate(&needs_merge)) {
+        return false;
+    }
+    if (needs_merge) {
+        LOG(INFO) << "Wait for merge (if any) before beginning a new update.";
+        auto state = ProcessUpdateState();
+        LOG(INFO) << "Merged with state = " << state;
+    }
+
+    auto file = LockExclusive();
+    if (!file) return false;
+
+    // Purge the ImageManager just in case there is a corrupt lp_metadata file
+    // lying around. (NB: no need to return false on an error, we can let the
+    // update try to progress.)
+    if (EnsureImageManager()) {
+        images_->RemoveAllImages();
+    }
+
+    auto state = ReadUpdateState(file.get());
+    if (state != UpdateState::None) {
+        LOG(ERROR) << "An update is already in progress, cannot begin a new update";
+        return false;
+    }
+    return WriteUpdateState(file.get(), UpdateState::Initiated);
+}
+
+bool SnapshotManager::CancelUpdate() {
+    bool needs_merge = false;
+    if (!TryCancelUpdate(&needs_merge)) {
+        return false;
+    }
+    if (needs_merge) {
+        LOG(ERROR) << "Cannot cancel update after it has completed or started merging";
+    }
+    return !needs_merge;
+}
+
+bool SnapshotManager::TryCancelUpdate(bool* needs_merge) {
+    *needs_merge = false;
+
+    auto file = LockExclusive();
+    if (!file) return false;
+
+    UpdateState state = ReadUpdateState(file.get());
+    if (state == UpdateState::None) return true;
+
+    if (state == UpdateState::Initiated) {
+        LOG(INFO) << "Update has been initiated, now canceling";
+        return RemoveAllUpdateState(file.get());
+    }
+
+    if (state == UpdateState::Unverified) {
+        // We completed an update, but it can still be canceled if we haven't booted into it.
+        auto slot = GetCurrentSlot();
+        if (slot != Slot::Target) {
+            LOG(INFO) << "Canceling previously completed updates (if any)";
+            return RemoveAllUpdateState(file.get());
+        }
+    }
+    *needs_merge = true;
+    return true;
+}
+
+SnapshotManager::Slot SnapshotManager::GetCurrentSlot() {
+    auto boot_file = GetSnapshotBootIndicatorPath();
+    std::string contents;
+    if (!android::base::ReadFileToString(boot_file, &contents)) {
+        PLOG(WARNING) << "Cannot read " << boot_file;
+        return Slot::Unknown;
+    }
+    if (device_->GetSlotSuffix() == contents) {
+        return Slot::Source;
+    }
+    return Slot::Target;
+}
+
+bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock) {
+    if (!RemoveAllSnapshots(lock)) {
+        LOG(ERROR) << "Could not remove all snapshots";
+        return false;
+    }
+
+    RemoveSnapshotBootIndicator();
+
+    // If this fails, we'll keep trying to remove the update state (as the
+    // device reboots or starts a new update) until it finally succeeds.
+    return WriteUpdateState(lock, UpdateState::None);
+}
+
+bool SnapshotManager::FinishedSnapshotWrites() {
+    auto lock = LockExclusive();
+    if (!lock) return false;
+
+    auto update_state = ReadUpdateState(lock.get());
+    if (update_state == UpdateState::Unverified) {
+        LOG(INFO) << "FinishedSnapshotWrites already called before. Ignored.";
+        return true;
+    }
+
+    if (update_state != UpdateState::Initiated) {
+        LOG(ERROR) << "Can only transition to the Unverified state from the Initiated state.";
+        return false;
+    }
+
+    if (!EnsureNoOverflowSnapshot(lock.get())) {
+        LOG(ERROR) << "Cannot ensure there are no overflow snapshots.";
+        return false;
+    }
+
+    // This file acts as both a quick indicator for init (it can use access(2)
+    // to decide how to do first-stage mounts), and it stores the old slot, so
+    // we can tell whether or not we performed a rollback.
+    auto contents = device_->GetSlotSuffix();
+    auto boot_file = GetSnapshotBootIndicatorPath();
+    if (!WriteStringToFileAtomic(contents, boot_file)) {
+        PLOG(ERROR) << "write failed: " << boot_file;
+        return false;
+    }
+    return WriteUpdateState(lock.get(), UpdateState::Unverified);
+}
+
+bool SnapshotManager::CreateSnapshot(LockedFile* lock, SnapshotStatus* status) {
+    CHECK(lock);
+    CHECK(lock->lock_mode() == LOCK_EX);
+    CHECK(status);
+
+    if (status->name().empty()) {
+        LOG(ERROR) << "SnapshotStatus has no name.";
+        return false;
+    }
+    // Sanity check these sizes. Like liblp, we guarantee the partition size
+    // is respected, which means it has to be sector-aligned. (This guarantee
+    // is useful for locating avb footers correctly). The COW file size, however,
+    // can be arbitrarily larger than specified, so we can safely round it up.
+    if (status->device_size() % kSectorSize != 0) {
+        LOG(ERROR) << "Snapshot " << status->name()
+                   << " device size is not a multiple of the sector size: "
+                   << status->device_size();
+        return false;
+    }
+    if (status->snapshot_size() % kSectorSize != 0) {
+        LOG(ERROR) << "Snapshot " << status->name()
+                   << " snapshot size is not a multiple of the sector size: "
+                   << status->snapshot_size();
+        return false;
+    }
+    if (status->cow_partition_size() % kSectorSize != 0) {
+        LOG(ERROR) << "Snapshot " << status->name()
+                   << " cow partition size is not a multiple of the sector size: "
+                   << status->cow_partition_size();
+        return false;
+    }
+    if (status->cow_file_size() % kSectorSize != 0) {
+        LOG(ERROR) << "Snapshot " << status->name()
+                   << " cow file size is not a multiple of the sector size: "
+                   << status->cow_file_size();
+        return false;
+    }
+
+    status->set_state(SnapshotState::CREATED);
+    status->set_sectors_allocated(0);
+    status->set_metadata_sectors(0);
+
+    if (!WriteSnapshotStatus(lock, *status)) {
+        PLOG(ERROR) << "Could not write snapshot status: " << status->name();
+        return false;
+    }
+    return true;
+}
+
+bool SnapshotManager::CreateCowImage(LockedFile* lock, const std::string& name) {
+    CHECK(lock);
+    CHECK(lock->lock_mode() == LOCK_EX);
+    if (!EnsureImageManager()) return false;
+
+    SnapshotStatus status;
+    if (!ReadSnapshotStatus(lock, name, &status)) {
+        return false;
+    }
+
+    // The COW file size should have been rounded up to the nearest sector in CreateSnapshot.
+    // Sanity check this.
+    if (status.cow_file_size() % kSectorSize != 0) {
+        LOG(ERROR) << "Snapshot " << name << " COW file size is not a multiple of the sector size: "
+                   << status.cow_file_size();
+        return false;
+    }
+
+    std::string cow_image_name = GetCowImageDeviceName(name);
+    int cow_flags = IImageManager::CREATE_IMAGE_DEFAULT;
+    return images_->CreateBackingImage(cow_image_name, status.cow_file_size(), cow_flags);
+}
+
+bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name,
+                                  const std::string& base_device, const std::string& cow_device,
+                                  const std::chrono::milliseconds& timeout_ms,
+                                  std::string* dev_path) {
+    CHECK(lock);
+
+    SnapshotStatus status;
+    if (!ReadSnapshotStatus(lock, name, &status)) {
+        return false;
+    }
+    if (status.state() == SnapshotState::NONE || status.state() == SnapshotState::MERGE_COMPLETED) {
+        LOG(ERROR) << "Should not create a snapshot device for " << name
+                   << " after merging has completed.";
+        return false;
+    }
+
+    // Validate the block device size, as well as the requested snapshot size.
+    // Note that during first-stage init, we don't have the device paths.
+    if (android::base::StartsWith(base_device, "/")) {
+        unique_fd fd(open(base_device.c_str(), O_RDONLY | O_CLOEXEC));
+        if (fd < 0) {
+            PLOG(ERROR) << "open failed: " << base_device;
+            return false;
+        }
+        auto dev_size = get_block_device_size(fd);
+        if (!dev_size) {
+            PLOG(ERROR) << "Could not determine block device size: " << base_device;
+            return false;
+        }
+        if (status.device_size() != dev_size) {
+            LOG(ERROR) << "Block device size for " << base_device << " does not match"
+                       << "(expected " << status.device_size() << ", got " << dev_size << ")";
+            return false;
+        }
+    }
+    if (status.device_size() % kSectorSize != 0) {
+        LOG(ERROR) << "invalid blockdev size for " << base_device << ": " << status.device_size();
+        return false;
+    }
+    if (status.snapshot_size() % kSectorSize != 0 ||
+        status.snapshot_size() > status.device_size()) {
+        LOG(ERROR) << "Invalid snapshot size for " << base_device << ": " << status.snapshot_size();
+        return false;
+    }
+    uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize;
+    uint64_t linear_sectors = (status.device_size() - status.snapshot_size()) / kSectorSize;
+
+    auto& dm = DeviceMapper::Instance();
+
+    // Note that merging is a global state. We do track whether individual devices
+    // have completed merging, but the start of the merge process is considered
+    // atomic.
+    SnapshotStorageMode mode;
+    switch (ReadUpdateState(lock)) {
+        case UpdateState::MergeCompleted:
+        case UpdateState::MergeNeedsReboot:
+            LOG(ERROR) << "Should not create a snapshot device for " << name
+                       << " after global merging has completed.";
+            return false;
+        case UpdateState::Merging:
+        case UpdateState::MergeFailed:
+            // Note: MergeFailed indicates that a merge is in progress, but
+            // is possibly stalled. We still have to honor the merge.
+            mode = SnapshotStorageMode::Merge;
+            break;
+        default:
+            mode = SnapshotStorageMode::Persistent;
+            break;
+    }
+
+    // The kernel (tested on 4.19) crashes horribly if a device has both a snapshot
+    // and a linear target in the same table. Instead, we stack them, and give the
+    // snapshot device a different name. It is not exposed to the caller in this
+    // case.
+    auto snap_name = (linear_sectors > 0) ? GetSnapshotExtraDeviceName(name) : name;
+
+    DmTable table;
+    table.Emplace<DmTargetSnapshot>(0, snapshot_sectors, base_device, cow_device, mode,
+                                    kSnapshotChunkSize);
+    if (!dm.CreateDevice(snap_name, table, dev_path, timeout_ms)) {
+        LOG(ERROR) << "Could not create snapshot device: " << snap_name;
+        return false;
+    }
+
+    if (linear_sectors) {
+        std::string snap_dev;
+        if (!dm.GetDeviceString(snap_name, &snap_dev)) {
+            LOG(ERROR) << "Cannot determine major/minor for: " << snap_name;
+            return false;
+        }
+
+        // Our stacking will looks like this:
+        //     [linear, linear] ; to snapshot, and non-snapshot region of base device
+        //     [snapshot-inner]
+        //     [base device]   [cow]
+        DmTable table;
+        table.Emplace<DmTargetLinear>(0, snapshot_sectors, snap_dev, 0);
+        table.Emplace<DmTargetLinear>(snapshot_sectors, linear_sectors, base_device,
+                                      snapshot_sectors);
+        if (!dm.CreateDevice(name, table, dev_path, timeout_ms)) {
+            LOG(ERROR) << "Could not create outer snapshot device: " << name;
+            dm.DeleteDevice(snap_name);
+            return false;
+        }
+    }
+
+    // :TODO: when merging is implemented, we need to add an argument to the
+    // status indicating how much progress is left to merge. (device-mapper
+    // does not retain the initial values, so we can't derive them.)
+    return true;
+}
+
+std::optional<std::string> SnapshotManager::MapCowImage(
+        const std::string& name, const std::chrono::milliseconds& timeout_ms) {
+    if (!EnsureImageManager()) return std::nullopt;
+    auto cow_image_name = GetCowImageDeviceName(name);
+
+    bool ok;
+    std::string cow_dev;
+    if (has_local_image_manager_) {
+        // If we forced a local image manager, it means we don't have binder,
+        // which means first-stage init. We must use device-mapper.
+        const auto& opener = device_->GetPartitionOpener();
+        ok = images_->MapImageWithDeviceMapper(opener, cow_image_name, &cow_dev);
+    } else {
+        ok = images_->MapImageDevice(cow_image_name, timeout_ms, &cow_dev);
+    }
+
+    if (ok) {
+        LOG(INFO) << "Mapped " << cow_image_name << " to " << cow_dev;
+        return cow_dev;
+    }
+    LOG(ERROR) << "Could not map image device: " << cow_image_name;
+    return std::nullopt;
+}
+
+bool SnapshotManager::UnmapSnapshot(LockedFile* lock, const std::string& name) {
+    CHECK(lock);
+
+    auto& dm = DeviceMapper::Instance();
+    if (!dm.DeleteDeviceIfExists(name)) {
+        LOG(ERROR) << "Could not delete snapshot device: " << name;
+        return false;
+    }
+
+    auto snapshot_extra_device = GetSnapshotExtraDeviceName(name);
+    if (!dm.DeleteDeviceIfExists(snapshot_extra_device)) {
+        LOG(ERROR) << "Could not delete snapshot inner device: " << snapshot_extra_device;
+        return false;
+    }
+
+    return true;
+}
+
+bool SnapshotManager::UnmapCowImage(const std::string& name) {
+    if (!EnsureImageManager()) return false;
+    return images_->UnmapImageIfExists(GetCowImageDeviceName(name));
+}
+
+bool SnapshotManager::DeleteSnapshot(LockedFile* lock, const std::string& name) {
+    CHECK(lock);
+    CHECK(lock->lock_mode() == LOCK_EX);
+    if (!EnsureImageManager()) return false;
+
+    if (!UnmapCowDevices(lock, name)) {
+        return false;
+    }
+
+    // We can't delete snapshots in recovery. The only way we'd try is it we're
+    // completing or canceling a merge in preparation for a data wipe, in which
+    // case, we don't care if the file sticks around.
+    if (device_->IsRecovery()) {
+        LOG(INFO) << "Skipping delete of snapshot " << name << " in recovery.";
+        return true;
+    }
+
+    auto cow_image_name = GetCowImageDeviceName(name);
+    if (images_->BackingImageExists(cow_image_name)) {
+        if (!images_->DeleteBackingImage(cow_image_name)) {
+            return false;
+        }
+    }
+
+    std::string error;
+    auto file_path = GetSnapshotStatusFilePath(name);
+    if (!android::base::RemoveFileIfExists(file_path, &error)) {
+        LOG(ERROR) << "Failed to remove status file " << file_path << ": " << error;
+        return false;
+    }
+    return true;
+}
+
+bool SnapshotManager::InitiateMerge() {
+    auto lock = LockExclusive();
+    if (!lock) return false;
+
+    UpdateState state = ReadUpdateState(lock.get());
+    if (state != UpdateState::Unverified) {
+        LOG(ERROR) << "Cannot begin a merge if an update has not been verified";
+        return false;
+    }
+
+    auto slot = GetCurrentSlot();
+    if (slot != Slot::Target) {
+        LOG(ERROR) << "Device cannot merge while not booting from new slot";
+        return false;
+    }
+
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(lock.get(), &snapshots)) {
+        LOG(ERROR) << "Could not list snapshots";
+        return false;
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    for (const auto& snapshot : snapshots) {
+        // The device has to be mapped, since everything should be merged at
+        // the same time. This is a fairly serious error. We could forcefully
+        // map everything here, but it should have been mapped during first-
+        // stage init.
+        if (dm.GetState(snapshot) == DmDeviceState::INVALID) {
+            LOG(ERROR) << "Cannot begin merge; device " << snapshot << " is not mapped.";
+            return false;
+        }
+    }
+
+    auto metadata = ReadCurrentMetadata();
+    for (auto it = snapshots.begin(); it != snapshots.end();) {
+        switch (GetMetadataPartitionState(*metadata, *it)) {
+            case MetadataPartitionState::Flashed:
+                LOG(WARNING) << "Detected re-flashing for partition " << *it
+                             << ". Skip merging it.";
+                [[fallthrough]];
+            case MetadataPartitionState::None: {
+                LOG(WARNING) << "Deleting snapshot for partition " << *it;
+                if (!DeleteSnapshot(lock.get(), *it)) {
+                    LOG(WARNING) << "Cannot delete snapshot for partition " << *it
+                                 << ". Skip merging it anyways.";
+                }
+                it = snapshots.erase(it);
+            } break;
+            case MetadataPartitionState::Updated: {
+                ++it;
+            } break;
+        }
+    }
+
+    // Point of no return - mark that we're starting a merge. From now on every
+    // snapshot must be a merge target.
+    if (!WriteUpdateState(lock.get(), UpdateState::Merging)) {
+        return false;
+    }
+
+    bool rewrote_all = true;
+    for (const auto& snapshot : snapshots) {
+        // If this fails, we have no choice but to continue. Everything must
+        // be merged. This is not an ideal state to be in, but it is safe,
+        // because we the next boot will try again.
+        if (!SwitchSnapshotToMerge(lock.get(), snapshot)) {
+            LOG(ERROR) << "Failed to switch snapshot to a merge target: " << snapshot;
+            rewrote_all = false;
+        }
+    }
+
+    // If we couldn't switch everything to a merge target, pre-emptively mark
+    // this merge as failed. It will get acknowledged when WaitForMerge() is
+    // called.
+    if (!rewrote_all) {
+        WriteUpdateState(lock.get(), UpdateState::MergeFailed);
+    }
+
+    // Return true no matter what, because a merge was initiated.
+    return true;
+}
+
+bool SnapshotManager::SwitchSnapshotToMerge(LockedFile* lock, const std::string& name) {
+    SnapshotStatus status;
+    if (!ReadSnapshotStatus(lock, name, &status)) {
+        return false;
+    }
+    if (status.state() != SnapshotState::CREATED) {
+        LOG(WARNING) << "Snapshot " << name
+                     << " has unexpected state: " << SnapshotState_Name(status.state());
+    }
+
+    // After this, we return true because we technically did switch to a merge
+    // target. Everything else we do here is just informational.
+    auto dm_name = GetSnapshotDeviceName(name, status);
+    if (!RewriteSnapshotDeviceTable(dm_name)) {
+        return false;
+    }
+
+    status.set_state(SnapshotState::MERGING);
+
+    DmTargetSnapshot::Status dm_status;
+    if (!QuerySnapshotStatus(dm_name, nullptr, &dm_status)) {
+        LOG(ERROR) << "Could not query merge status for snapshot: " << dm_name;
+    }
+    status.set_sectors_allocated(dm_status.sectors_allocated);
+    status.set_metadata_sectors(dm_status.metadata_sectors);
+    if (!WriteSnapshotStatus(lock, status)) {
+        LOG(ERROR) << "Could not update status file for snapshot: " << name;
+    }
+    return true;
+}
+
+bool SnapshotManager::RewriteSnapshotDeviceTable(const std::string& dm_name) {
+    auto& dm = DeviceMapper::Instance();
+
+    std::vector<DeviceMapper::TargetInfo> old_targets;
+    if (!dm.GetTableInfo(dm_name, &old_targets)) {
+        LOG(ERROR) << "Could not read snapshot device table: " << dm_name;
+        return false;
+    }
+    if (old_targets.size() != 1 || DeviceMapper::GetTargetType(old_targets[0].spec) != "snapshot") {
+        LOG(ERROR) << "Unexpected device-mapper table for snapshot: " << dm_name;
+        return false;
+    }
+
+    std::string base_device, cow_device;
+    if (!DmTargetSnapshot::GetDevicesFromParams(old_targets[0].data, &base_device, &cow_device)) {
+        LOG(ERROR) << "Could not derive underlying devices for snapshot: " << dm_name;
+        return false;
+    }
+
+    DmTable table;
+    table.Emplace<DmTargetSnapshot>(0, old_targets[0].spec.length, base_device, cow_device,
+                                    SnapshotStorageMode::Merge, kSnapshotChunkSize);
+    if (!dm.LoadTableAndActivate(dm_name, table)) {
+        LOG(ERROR) << "Could not swap device-mapper tables on snapshot device " << dm_name;
+        return false;
+    }
+    LOG(INFO) << "Successfully switched snapshot device to a merge target: " << dm_name;
+    return true;
+}
+
+enum class TableQuery {
+    Table,
+    Status,
+};
+
+static bool GetSingleTarget(const std::string& dm_name, TableQuery query,
+                            DeviceMapper::TargetInfo* target) {
+    auto& dm = DeviceMapper::Instance();
+    if (dm.GetState(dm_name) == DmDeviceState::INVALID) {
+        return false;
+    }
+
+    std::vector<DeviceMapper::TargetInfo> targets;
+    bool result;
+    if (query == TableQuery::Status) {
+        result = dm.GetTableStatus(dm_name, &targets);
+    } else {
+        result = dm.GetTableInfo(dm_name, &targets);
+    }
+    if (!result) {
+        LOG(ERROR) << "Could not query device: " << dm_name;
+        return false;
+    }
+    if (targets.size() != 1) {
+        return false;
+    }
+
+    *target = std::move(targets[0]);
+    return true;
+}
+
+bool SnapshotManager::IsSnapshotDevice(const std::string& dm_name, TargetInfo* target) {
+    DeviceMapper::TargetInfo snap_target;
+    if (!GetSingleTarget(dm_name, TableQuery::Status, &snap_target)) {
+        return false;
+    }
+    auto type = DeviceMapper::GetTargetType(snap_target.spec);
+    if (type != "snapshot" && type != "snapshot-merge") {
+        return false;
+    }
+    if (target) {
+        *target = std::move(snap_target);
+    }
+    return true;
+}
+
+bool SnapshotManager::QuerySnapshotStatus(const std::string& dm_name, std::string* target_type,
+                                          DmTargetSnapshot::Status* status) {
+    DeviceMapper::TargetInfo target;
+    if (!IsSnapshotDevice(dm_name, &target)) {
+        LOG(ERROR) << "Device " << dm_name << " is not a snapshot or snapshot-merge device";
+        return false;
+    }
+    if (!DmTargetSnapshot::ParseStatusText(target.data, status)) {
+        LOG(ERROR) << "Could not parse snapshot status text: " << dm_name;
+        return false;
+    }
+    if (target_type) {
+        *target_type = DeviceMapper::GetTargetType(target.spec);
+    }
+    return true;
+}
+
+// Note that when a merge fails, we will *always* try again to complete the
+// merge each time the device boots. There is no harm in doing so, and if
+// the problem was transient, we might manage to get a new outcome.
+UpdateState SnapshotManager::ProcessUpdateState(const std::function<void()>& callback) {
+    while (true) {
+        UpdateState state = CheckMergeState();
+        if (state == UpdateState::MergeFailed) {
+            AcknowledgeMergeFailure();
+        }
+        if (state != UpdateState::Merging) {
+            // Either there is no merge, or the merge was finished, so no need
+            // to keep waiting.
+            return state;
+        }
+
+        if (callback) {
+            callback();
+        }
+
+        // This wait is not super time sensitive, so we have a relatively
+        // low polling frequency.
+        std::this_thread::sleep_for(kUpdateStateCheckInterval);
+    }
+}
+
+UpdateState SnapshotManager::CheckMergeState() {
+    auto lock = LockExclusive();
+    if (!lock) {
+        return UpdateState::MergeFailed;
+    }
+
+    UpdateState state = CheckMergeState(lock.get());
+    if (state == UpdateState::MergeCompleted) {
+        // Do this inside the same lock. Failures get acknowledged without the
+        // lock, because flock() might have failed.
+        AcknowledgeMergeSuccess(lock.get());
+    } else if (state == UpdateState::Cancelled) {
+        RemoveAllUpdateState(lock.get());
+    }
+    return state;
+}
+
+UpdateState SnapshotManager::CheckMergeState(LockedFile* lock) {
+    UpdateState state = ReadUpdateState(lock);
+    switch (state) {
+        case UpdateState::None:
+        case UpdateState::MergeCompleted:
+            // Harmless races are allowed between two callers of WaitForMerge,
+            // so in both of these cases we just propagate the state.
+            return state;
+
+        case UpdateState::Merging:
+        case UpdateState::MergeNeedsReboot:
+        case UpdateState::MergeFailed:
+            // We'll poll each snapshot below. Note that for the NeedsReboot
+            // case, we always poll once to give cleanup another opportunity to
+            // run.
+            break;
+
+        case UpdateState::Unverified:
+            // This is an edge case. Normally cancelled updates are detected
+            // via the merge poll below, but if we never started a merge, we
+            // need to also check here.
+            if (HandleCancelledUpdate(lock)) {
+                return UpdateState::Cancelled;
+            }
+            return state;
+
+        default:
+            return state;
+    }
+
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(lock, &snapshots)) {
+        return UpdateState::MergeFailed;
+    }
+
+    bool cancelled = false;
+    bool failed = false;
+    bool merging = false;
+    bool needs_reboot = false;
+    for (const auto& snapshot : snapshots) {
+        UpdateState snapshot_state = CheckTargetMergeState(lock, snapshot);
+        switch (snapshot_state) {
+            case UpdateState::MergeFailed:
+                failed = true;
+                break;
+            case UpdateState::Merging:
+                merging = true;
+                break;
+            case UpdateState::MergeNeedsReboot:
+                needs_reboot = true;
+                break;
+            case UpdateState::MergeCompleted:
+                break;
+            case UpdateState::Cancelled:
+                cancelled = true;
+                break;
+            default:
+                LOG(ERROR) << "Unknown merge status: " << static_cast<uint32_t>(snapshot_state);
+                failed = true;
+                break;
+        }
+    }
+
+    if (merging) {
+        // Note that we handle "Merging" before we handle anything else. We
+        // want to poll until *nothing* is merging if we can, so everything has
+        // a chance to get marked as completed or failed.
+        return UpdateState::Merging;
+    }
+    if (failed) {
+        // Note: since there are many drop-out cases for failure, we acknowledge
+        // it in WaitForMerge rather than here and elsewhere.
+        return UpdateState::MergeFailed;
+    }
+    if (needs_reboot) {
+        WriteUpdateState(lock, UpdateState::MergeNeedsReboot);
+        return UpdateState::MergeNeedsReboot;
+    }
+    if (cancelled) {
+        // This is an edge case, that we handle as correctly as we sensibly can.
+        // The underlying partition has changed behind update_engine, and we've
+        // removed the snapshot as a result. The exact state of the update is
+        // undefined now, but this can only happen on an unlocked device where
+        // partitions can be flashed without wiping userdata.
+        return UpdateState::Cancelled;
+    }
+    return UpdateState::MergeCompleted;
+}
+
+UpdateState SnapshotManager::CheckTargetMergeState(LockedFile* lock, const std::string& name) {
+    SnapshotStatus snapshot_status;
+    if (!ReadSnapshotStatus(lock, name, &snapshot_status)) {
+        return UpdateState::MergeFailed;
+    }
+
+    std::string dm_name = GetSnapshotDeviceName(name, snapshot_status);
+
+    std::unique_ptr<LpMetadata> current_metadata;
+
+    if (!IsSnapshotDevice(dm_name)) {
+        if (!current_metadata) {
+            current_metadata = ReadCurrentMetadata();
+        }
+
+        if (!current_metadata ||
+            GetMetadataPartitionState(*current_metadata, name) != MetadataPartitionState::Updated) {
+            DeleteSnapshot(lock, name);
+            return UpdateState::Cancelled;
+        }
+
+        // During a check, we decided the merge was complete, but we were unable to
+        // collapse the device-mapper stack and perform COW cleanup. If we haven't
+        // rebooted after this check, the device will still be a snapshot-merge
+        // target. If the have rebooted, the device will now be a linear target,
+        // and we can try cleanup again.
+        if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
+            // NB: It's okay if this fails now, we gave cleanup our best effort.
+            OnSnapshotMergeComplete(lock, name, snapshot_status);
+            return UpdateState::MergeCompleted;
+        }
+
+        LOG(ERROR) << "Expected snapshot or snapshot-merge for device: " << dm_name;
+        return UpdateState::MergeFailed;
+    }
+
+    // This check is expensive so it is only enabled for debugging.
+    DCHECK((current_metadata = ReadCurrentMetadata()) &&
+           GetMetadataPartitionState(*current_metadata, name) == MetadataPartitionState::Updated);
+
+    std::string target_type;
+    DmTargetSnapshot::Status status;
+    if (!QuerySnapshotStatus(dm_name, &target_type, &status)) {
+        return UpdateState::MergeFailed;
+    }
+    if (target_type != "snapshot-merge") {
+        // We can get here if we failed to rewrite the target type in
+        // InitiateMerge(). If we failed to create the target in first-stage
+        // init, boot would not succeed.
+        LOG(ERROR) << "Snapshot " << name << " has incorrect target type: " << target_type;
+        return UpdateState::MergeFailed;
+    }
+
+    // These two values are equal when merging is complete.
+    if (status.sectors_allocated != status.metadata_sectors) {
+        if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
+            LOG(ERROR) << "Snapshot " << name << " is merging after being marked merge-complete.";
+            return UpdateState::MergeFailed;
+        }
+        return UpdateState::Merging;
+    }
+
+    // Merging is done. First, update the status file to indicate the merge
+    // is complete. We do this before calling OnSnapshotMergeComplete, even
+    // though this means the write is potentially wasted work (since in the
+    // ideal case we'll immediately delete the file).
+    //
+    // This makes it simpler to reason about the next reboot: no matter what
+    // part of cleanup failed, first-stage init won't try to create another
+    // snapshot device for this partition.
+    snapshot_status.set_state(SnapshotState::MERGE_COMPLETED);
+    if (!WriteSnapshotStatus(lock, snapshot_status)) {
+        return UpdateState::MergeFailed;
+    }
+    if (!OnSnapshotMergeComplete(lock, name, snapshot_status)) {
+        return UpdateState::MergeNeedsReboot;
+    }
+    return UpdateState::MergeCompleted;
+}
+
+std::string SnapshotManager::GetSnapshotBootIndicatorPath() {
+    return metadata_dir_ + "/" + android::base::Basename(kBootIndicatorPath);
+}
+
+void SnapshotManager::RemoveSnapshotBootIndicator() {
+    // It's okay if this fails - first-stage init performs a deeper check after
+    // reading the indicator file, so it's not a problem if it still exists
+    // after the update completes.
+    auto boot_file = GetSnapshotBootIndicatorPath();
+    if (unlink(boot_file.c_str()) == -1 && errno != ENOENT) {
+        PLOG(ERROR) << "unlink " << boot_file;
+    }
+}
+
+void SnapshotManager::AcknowledgeMergeSuccess(LockedFile* lock) {
+    RemoveAllUpdateState(lock);
+}
+
+void SnapshotManager::AcknowledgeMergeFailure() {
+    // Log first, so worst case, we always have a record of why the calls below
+    // were being made.
+    LOG(ERROR) << "Merge could not be completed and will be marked as failed.";
+
+    auto lock = LockExclusive();
+    if (!lock) return;
+
+    // Since we released the lock in between WaitForMerge and here, it's
+    // possible (1) the merge successfully completed or (2) was already
+    // marked as a failure. So make sure to check the state again, and
+    // only mark as a failure if appropriate.
+    UpdateState state = ReadUpdateState(lock.get());
+    if (state != UpdateState::Merging && state != UpdateState::MergeNeedsReboot) {
+        return;
+    }
+
+    WriteUpdateState(lock.get(), UpdateState::MergeFailed);
+}
+
+bool SnapshotManager::OnSnapshotMergeComplete(LockedFile* lock, const std::string& name,
+                                              const SnapshotStatus& status) {
+    auto dm_name = GetSnapshotDeviceName(name, status);
+    if (IsSnapshotDevice(dm_name)) {
+        // We are extra-cautious here, to avoid deleting the wrong table.
+        std::string target_type;
+        DmTargetSnapshot::Status dm_status;
+        if (!QuerySnapshotStatus(dm_name, &target_type, &dm_status)) {
+            return false;
+        }
+        if (target_type != "snapshot-merge") {
+            LOG(ERROR) << "Unexpected target type " << target_type
+                       << " for snapshot device: " << dm_name;
+            return false;
+        }
+        if (dm_status.sectors_allocated != dm_status.metadata_sectors) {
+            LOG(ERROR) << "Merge is unexpectedly incomplete for device " << dm_name;
+            return false;
+        }
+        if (!CollapseSnapshotDevice(name, status)) {
+            LOG(ERROR) << "Unable to collapse snapshot: " << name;
+            return false;
+        }
+        // Note that collapsing is implicitly an Unmap, so we don't need to
+        // unmap the snapshot.
+    }
+
+    if (!DeleteSnapshot(lock, name)) {
+        LOG(ERROR) << "Could not delete snapshot: " << name;
+        return false;
+    }
+    return true;
+}
+
+bool SnapshotManager::CollapseSnapshotDevice(const std::string& name,
+                                             const SnapshotStatus& status) {
+    auto& dm = DeviceMapper::Instance();
+    auto dm_name = GetSnapshotDeviceName(name, status);
+
+    // Verify we have a snapshot-merge device.
+    DeviceMapper::TargetInfo target;
+    if (!GetSingleTarget(dm_name, TableQuery::Table, &target)) {
+        return false;
+    }
+    if (DeviceMapper::GetTargetType(target.spec) != "snapshot-merge") {
+        // This should be impossible, it was checked earlier.
+        LOG(ERROR) << "Snapshot device has invalid target type: " << dm_name;
+        return false;
+    }
+
+    std::string base_device, cow_device;
+    if (!DmTargetSnapshot::GetDevicesFromParams(target.data, &base_device, &cow_device)) {
+        LOG(ERROR) << "Could not parse snapshot device " << dm_name
+                   << " parameters: " << target.data;
+        return false;
+    }
+
+    uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize;
+    if (snapshot_sectors * kSectorSize != status.snapshot_size()) {
+        LOG(ERROR) << "Snapshot " << name
+                   << " size is not sector aligned: " << status.snapshot_size();
+        return false;
+    }
+
+    if (dm_name != name) {
+        // We've derived the base device, but we actually need to replace the
+        // table of the outermost device. Do a quick verification that this
+        // device looks like we expect it to.
+        std::vector<DeviceMapper::TargetInfo> outer_table;
+        if (!dm.GetTableInfo(name, &outer_table)) {
+            LOG(ERROR) << "Could not validate outer snapshot table: " << name;
+            return false;
+        }
+        if (outer_table.size() != 2) {
+            LOG(ERROR) << "Expected 2 dm-linear targets for table " << name
+                       << ", got: " << outer_table.size();
+            return false;
+        }
+        for (const auto& target : outer_table) {
+            auto target_type = DeviceMapper::GetTargetType(target.spec);
+            if (target_type != "linear") {
+                LOG(ERROR) << "Outer snapshot table may only contain linear targets, but " << name
+                           << " has target: " << target_type;
+                return false;
+            }
+        }
+        if (outer_table[0].spec.length != snapshot_sectors) {
+            LOG(ERROR) << "dm-snapshot " << name << " should have " << snapshot_sectors
+                       << " sectors, got: " << outer_table[0].spec.length;
+            return false;
+        }
+        uint64_t expected_device_sectors = status.device_size() / kSectorSize;
+        uint64_t actual_device_sectors = outer_table[0].spec.length + outer_table[1].spec.length;
+        if (expected_device_sectors != actual_device_sectors) {
+            LOG(ERROR) << "Outer device " << name << " should have " << expected_device_sectors
+                       << " sectors, got: " << actual_device_sectors;
+            return false;
+        }
+    }
+
+    uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
+    // Create a DmTable that is identical to the base device.
+    CreateLogicalPartitionParams base_device_params{
+            .block_device = device_->GetSuperDevice(slot),
+            .metadata_slot = slot,
+            .partition_name = name,
+            .partition_opener = &device_->GetPartitionOpener(),
+    };
+    DmTable table;
+    if (!CreateDmTable(base_device_params, &table)) {
+        LOG(ERROR) << "Could not create a DmTable for partition: " << name;
+        return false;
+    }
+
+    // Note: we are replacing the *outer* table here, so we do not use dm_name.
+    if (!dm.LoadTableAndActivate(name, table)) {
+        return false;
+    }
+
+    // Attempt to delete the snapshot device if one still exists. Nothing
+    // should be depending on the device, and device-mapper should have
+    // flushed remaining I/O. We could in theory replace with dm-zero (or
+    // re-use the table above), but for now it's better to know why this
+    // would fail.
+    if (dm_name != name && !dm.DeleteDeviceIfExists(dm_name)) {
+        LOG(ERROR) << "Unable to delete snapshot device " << dm_name << ", COW cannot be "
+                   << "reclaimed until after reboot.";
+        return false;
+    }
+
+    // Cleanup the base device as well, since it is no longer used. This does
+    // not block cleanup.
+    auto base_name = GetBaseDeviceName(name);
+    if (!dm.DeleteDeviceIfExists(base_name)) {
+        LOG(ERROR) << "Unable to delete base device for snapshot: " << base_name;
+    }
+    return true;
+}
+
+bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock) {
+    auto slot = GetCurrentSlot();
+    if (slot == Slot::Unknown) {
+        return false;
+    }
+    if (slot == Slot::Target) {
+        // We're booted into the target slot, which means we just rebooted
+        // after applying the update.
+        if (!HandleCancelledUpdateOnNewSlot(lock)) {
+            return false;
+        }
+    }
+
+    // The only way we can get here is if:
+    //  (1) The device rolled back to the previous slot.
+    //  (2) This function was called prematurely before rebooting the device.
+    //  (3) fastboot set_active was used.
+    //  (4) The device updates to the new slot but re-flashed *all* partitions
+    //      in the new slot.
+    //
+    // In any case, delete the snapshots. It may be worth using the boot_control
+    // HAL to differentiate case (2).
+    RemoveAllUpdateState(lock);
+    return true;
+}
+
+std::unique_ptr<LpMetadata> SnapshotManager::ReadCurrentMetadata() {
+    const auto& opener = device_->GetPartitionOpener();
+    uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
+    auto super_device = device_->GetSuperDevice(slot);
+    auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
+    if (!metadata) {
+        LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
+        return nullptr;
+    }
+    return metadata;
+}
+
+SnapshotManager::MetadataPartitionState SnapshotManager::GetMetadataPartitionState(
+        const LpMetadata& metadata, const std::string& name) {
+    auto partition = android::fs_mgr::FindPartition(metadata, name);
+    if (!partition) return MetadataPartitionState::None;
+    if (partition->attributes & LP_PARTITION_ATTR_UPDATED) {
+        return MetadataPartitionState::Updated;
+    }
+    return MetadataPartitionState::Flashed;
+}
+
+bool SnapshotManager::HandleCancelledUpdateOnNewSlot(LockedFile* lock) {
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(lock, &snapshots)) {
+        LOG(WARNING) << "Failed to list snapshots to determine whether device has been flashed "
+                     << "after applying an update. Assuming no snapshots.";
+        // Let HandleCancelledUpdate resets UpdateState.
+        return true;
+    }
+
+    // Attempt to detect re-flashing on each partition.
+    // - If all partitions are re-flashed, we can proceed to cancel the whole update.
+    // - If only some of the partitions are re-flashed, snapshots for re-flashed partitions are
+    //   deleted. Caller is responsible for merging the rest of the snapshots.
+    // - If none of the partitions are re-flashed, caller is responsible for merging the snapshots.
+    auto metadata = ReadCurrentMetadata();
+    if (!metadata) return false;
+    bool all_snapshot_cancelled = true;
+    for (const auto& snapshot_name : snapshots) {
+        if (GetMetadataPartitionState(*metadata, snapshot_name) ==
+            MetadataPartitionState::Updated) {
+            LOG(WARNING) << "Cannot cancel update because snapshot" << snapshot_name
+                         << " is in use.";
+            all_snapshot_cancelled = false;
+            continue;
+        }
+        // Delete snapshots for partitions that are re-flashed after the update.
+        LOG(INFO) << "Detected re-flashing of partition " << snapshot_name << ".";
+        if (!DeleteSnapshot(lock, snapshot_name)) {
+            // This is an error, but it is okay to leave the snapshot in the short term.
+            // However, if all_snapshot_cancelled == false after exiting the loop, caller may
+            // initiate merge for this unused snapshot, which is likely to fail.
+            LOG(WARNING) << "Failed to delete snapshot for re-flashed partition " << snapshot_name;
+        }
+    }
+    if (!all_snapshot_cancelled) return false;
+
+    LOG(INFO) << "All partitions are re-flashed after update, removing all update states.";
+    return true;
+}
+
+bool SnapshotManager::RemoveAllSnapshots(LockedFile* lock) {
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(lock, &snapshots)) {
+        LOG(ERROR) << "Could not list snapshots";
+        return false;
+    }
+
+    bool ok = true;
+    bool has_mapped_cow_images = false;
+    for (const auto& name : snapshots) {
+        if (!UnmapPartitionWithSnapshot(lock, name) || !DeleteSnapshot(lock, name)) {
+            // Remember whether or not we were able to unmap the cow image.
+            auto cow_image_device = GetCowImageDeviceName(name);
+            has_mapped_cow_images |= images_->IsImageMapped(cow_image_device);
+
+            ok = false;
+        }
+    }
+
+    if (ok || !has_mapped_cow_images) {
+        // Delete any image artifacts as a precaution, in case an update is
+        // being cancelled due to some corrupted state in an lp_metadata file.
+        // Note that we do not do this if some cow images are still mapped,
+        // since we must not remove backing storage if it's in use.
+        if (!EnsureImageManager() || !images_->RemoveAllImages()) {
+            LOG(ERROR) << "Could not remove all snapshot artifacts";
+            return false;
+        }
+    }
+    return ok;
+}
+
+UpdateState SnapshotManager::GetUpdateState(double* progress) {
+    // If we've never started an update, the state file won't exist.
+    auto state_file = GetStateFilePath();
+    if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
+        return UpdateState::None;
+    }
+
+    auto lock = LockShared();
+    if (!lock) {
+        return UpdateState::None;
+    }
+
+    auto state = ReadUpdateState(lock.get());
+    if (progress) {
+        *progress = 0.0;
+        if (state == UpdateState::Merging) {
+            // :TODO: When merging is implemented, set progress_val.
+        } else if (state == UpdateState::MergeCompleted) {
+            *progress = 100.0;
+        }
+    }
+    return state;
+}
+
+bool SnapshotManager::ListSnapshots(LockedFile* lock, std::vector<std::string>* snapshots) {
+    CHECK(lock);
+
+    auto dir_path = metadata_dir_ + "/snapshots"s;
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dir_path.c_str()), closedir);
+    if (!dir) {
+        PLOG(ERROR) << "opendir failed: " << dir_path;
+        return false;
+    }
+
+    struct dirent* dp;
+    while ((dp = readdir(dir.get())) != nullptr) {
+        if (dp->d_type != DT_REG) continue;
+        snapshots->emplace_back(dp->d_name);
+    }
+    return true;
+}
+
+bool SnapshotManager::IsSnapshotManagerNeeded() {
+    return access(kBootIndicatorPath, F_OK) == 0;
+}
+
+bool SnapshotManager::NeedSnapshotsInFirstStageMount() {
+    // If we fail to read, we'll wind up using CreateLogicalPartitions, which
+    // will create devices that look like the old slot, except with extra
+    // content at the end of each device. This will confuse dm-verity, and
+    // ultimately we'll fail to boot. Why not make it a fatal error and have
+    // the reason be clearer? Because the indicator file still exists, and
+    // if this was FATAL, reverting to the old slot would be broken.
+    auto slot = GetCurrentSlot();
+    if (slot != Slot::Target) {
+        LOG(INFO) << "Not booting from new slot. Will not mount snapshots.";
+        return false;
+    }
+
+    // If we can't read the update state, it's unlikely anything else will
+    // succeed, so this is a fatal error. We'll eventually exhaust boot
+    // attempts and revert to the old slot.
+    auto lock = LockShared();
+    if (!lock) {
+        LOG(FATAL) << "Could not read update state to determine snapshot status";
+        return false;
+    }
+    switch (ReadUpdateState(lock.get())) {
+        case UpdateState::Unverified:
+        case UpdateState::Merging:
+        case UpdateState::MergeFailed:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool SnapshotManager::CreateLogicalAndSnapshotPartitions(const std::string& super_device) {
+    LOG(INFO) << "Creating logical partitions with snapshots as needed";
+
+    auto lock = LockExclusive();
+    if (!lock) return false;
+
+    const auto& opener = device_->GetPartitionOpener();
+    uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
+    auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
+    if (!metadata) {
+        LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
+        return false;
+    }
+
+    for (const auto& partition : metadata->partitions) {
+        if (GetPartitionGroupName(metadata->groups[partition.group_index]) == kCowGroupName) {
+            LOG(INFO) << "Skip mapping partition " << GetPartitionName(partition) << " in group "
+                      << kCowGroupName;
+            continue;
+        }
+
+        CreateLogicalPartitionParams params = {
+                .block_device = super_device,
+                .metadata = metadata.get(),
+                .partition = &partition,
+                .partition_opener = &opener,
+        };
+        std::string ignore_path;
+        if (!MapPartitionWithSnapshot(lock.get(), std::move(params), &ignore_path)) {
+            return false;
+        }
+    }
+
+    LOG(INFO) << "Created logical partitions with snapshot.";
+    return true;
+}
+
+static std::chrono::milliseconds GetRemainingTime(
+        const std::chrono::milliseconds& timeout,
+        const std::chrono::time_point<std::chrono::steady_clock>& begin) {
+    // If no timeout is specified, execute all commands without specifying any timeout.
+    if (timeout.count() == 0) return std::chrono::milliseconds(0);
+    auto passed_time = std::chrono::steady_clock::now() - begin;
+    auto remaining_time = timeout - duration_cast<std::chrono::milliseconds>(passed_time);
+    if (remaining_time.count() <= 0) {
+        LOG(ERROR) << "MapPartitionWithSnapshot has reached timeout " << timeout.count() << "ms ("
+                   << remaining_time.count() << "ms remaining)";
+        // Return min() instead of remaining_time here because 0 is treated as a special value for
+        // no timeout, where the rest of the commands will still be executed.
+        return std::chrono::milliseconds::min();
+    }
+    return remaining_time;
+}
+
+bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
+                                               CreateLogicalPartitionParams params,
+                                               std::string* path) {
+    auto begin = std::chrono::steady_clock::now();
+
+    CHECK(lock);
+    path->clear();
+
+    if (params.GetPartitionName() != params.GetDeviceName()) {
+        LOG(ERROR) << "Mapping snapshot with a different name is unsupported: partition_name = "
+                   << params.GetPartitionName() << ", device_name = " << params.GetDeviceName();
+        return false;
+    }
+
+    // Fill out fields in CreateLogicalPartitionParams so that we have more information (e.g. by
+    // reading super partition metadata).
+    CreateLogicalPartitionParams::OwnedData params_owned_data;
+    if (!params.InitDefaults(&params_owned_data)) {
+        return false;
+    }
+
+    if (!params.partition->num_extents) {
+        LOG(INFO) << "Skipping zero-length logical partition: " << params.GetPartitionName();
+        return true;  // leave path empty to indicate that nothing is mapped.
+    }
+
+    // Determine if there is a live snapshot for the SnapshotStatus of the partition; i.e. if the
+    // partition still has a snapshot that needs to be mapped.  If no live snapshot or merge
+    // completed, live_snapshot_status is set to nullopt.
+    std::optional<SnapshotStatus> live_snapshot_status;
+    do {
+        if (!(params.partition->attributes & LP_PARTITION_ATTR_UPDATED)) {
+            LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
+                      << params.GetPartitionName();
+            break;
+        }
+        auto file_path = GetSnapshotStatusFilePath(params.GetPartitionName());
+        if (access(file_path.c_str(), F_OK) != 0) {
+            if (errno != ENOENT) {
+                PLOG(INFO) << "Can't map snapshot for " << params.GetPartitionName()
+                           << ": Can't access " << file_path;
+                return false;
+            }
+            break;
+        }
+        live_snapshot_status = std::make_optional<SnapshotStatus>();
+        if (!ReadSnapshotStatus(lock, params.GetPartitionName(), &*live_snapshot_status)) {
+            return false;
+        }
+        // No live snapshot if merge is completed.
+        if (live_snapshot_status->state() == SnapshotState::MERGE_COMPLETED) {
+            live_snapshot_status.reset();
+        }
+
+        if (live_snapshot_status->state() == SnapshotState::NONE ||
+            live_snapshot_status->cow_partition_size() + live_snapshot_status->cow_file_size() ==
+                    0) {
+            LOG(WARNING) << "Snapshot status for " << params.GetPartitionName()
+                         << " is invalid, ignoring: state = "
+                         << SnapshotState_Name(live_snapshot_status->state())
+                         << ", cow_partition_size = " << live_snapshot_status->cow_partition_size()
+                         << ", cow_file_size = " << live_snapshot_status->cow_file_size();
+            live_snapshot_status.reset();
+        }
+    } while (0);
+
+    if (live_snapshot_status.has_value()) {
+        // dm-snapshot requires the base device to be writable.
+        params.force_writable = true;
+        // Map the base device with a different name to avoid collision.
+        params.device_name = GetBaseDeviceName(params.GetPartitionName());
+    }
+
+    AutoDeviceList created_devices;
+
+    // Create the base device for the snapshot, or if there is no snapshot, the
+    // device itself. This device consists of the real blocks in the super
+    // partition that this logical partition occupies.
+    auto& dm = DeviceMapper::Instance();
+    std::string base_path;
+    if (!CreateLogicalPartition(params, &base_path)) {
+        LOG(ERROR) << "Could not create logical partition " << params.GetPartitionName()
+                   << " as device " << params.GetDeviceName();
+        return false;
+    }
+    created_devices.EmplaceBack<AutoUnmapDevice>(&dm, params.GetDeviceName());
+
+    if (!live_snapshot_status.has_value()) {
+        *path = base_path;
+        created_devices.Release();
+        return true;
+    }
+
+    // We don't have ueventd in first-stage init, so use device major:minor
+    // strings instead.
+    std::string base_device;
+    if (!dm.GetDeviceString(params.GetDeviceName(), &base_device)) {
+        LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
+        return false;
+    }
+
+    auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
+    if (remaining_time.count() < 0) return false;
+
+    std::string cow_name;
+    CreateLogicalPartitionParams cow_params = params;
+    cow_params.timeout_ms = remaining_time;
+    if (!MapCowDevices(lock, cow_params, *live_snapshot_status, &created_devices, &cow_name)) {
+        return false;
+    }
+    std::string cow_device;
+    if (!dm.GetDeviceString(cow_name, &cow_device)) {
+        LOG(ERROR) << "Could not determine major/minor for: " << cow_name;
+        return false;
+    }
+
+    remaining_time = GetRemainingTime(params.timeout_ms, begin);
+    if (remaining_time.count() < 0) return false;
+
+    if (!MapSnapshot(lock, params.GetPartitionName(), base_device, cow_device, remaining_time,
+                     path)) {
+        LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName();
+        return false;
+    }
+    // No need to add params.GetPartitionName() to created_devices since it is immediately released.
+
+    created_devices.Release();
+
+    LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << *path;
+
+    return true;
+}
+
+bool SnapshotManager::UnmapPartitionWithSnapshot(LockedFile* lock,
+                                                 const std::string& target_partition_name) {
+    CHECK(lock);
+
+    if (!UnmapSnapshot(lock, target_partition_name)) {
+        return false;
+    }
+
+    if (!UnmapCowDevices(lock, target_partition_name)) {
+        return false;
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    std::string base_name = GetBaseDeviceName(target_partition_name);
+    if (!dm.DeleteDeviceIfExists(base_name)) {
+        LOG(ERROR) << "Cannot delete base device: " << base_name;
+        return false;
+    }
+
+    LOG(INFO) << "Successfully unmapped snapshot " << target_partition_name;
+
+    return true;
+}
+
+bool SnapshotManager::MapCowDevices(LockedFile* lock, const CreateLogicalPartitionParams& params,
+                                    const SnapshotStatus& snapshot_status,
+                                    AutoDeviceList* created_devices, std::string* cow_name) {
+    CHECK(lock);
+    CHECK(snapshot_status.cow_partition_size() + snapshot_status.cow_file_size() > 0);
+    auto begin = std::chrono::steady_clock::now();
+
+    std::string partition_name = params.GetPartitionName();
+    std::string cow_image_name = GetCowImageDeviceName(partition_name);
+    *cow_name = GetCowName(partition_name);
+
+    auto& dm = DeviceMapper::Instance();
+
+    // Map COW image if necessary.
+    if (snapshot_status.cow_file_size() > 0) {
+        if (!EnsureImageManager()) return false;
+        auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
+        if (remaining_time.count() < 0) return false;
+
+        if (!MapCowImage(partition_name, remaining_time).has_value()) {
+            LOG(ERROR) << "Could not map cow image for partition: " << partition_name;
+            return false;
+        }
+        created_devices->EmplaceBack<AutoUnmapImage>(images_.get(), cow_image_name);
+
+        // If no COW partition exists, just return the image alone.
+        if (snapshot_status.cow_partition_size() == 0) {
+            *cow_name = std::move(cow_image_name);
+            LOG(INFO) << "Mapped COW image for " << partition_name << " at " << *cow_name;
+            return true;
+        }
+    }
+
+    auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
+    if (remaining_time.count() < 0) return false;
+
+    CHECK(snapshot_status.cow_partition_size() > 0);
+
+    // Create the DmTable for the COW device. It is the DmTable of the COW partition plus
+    // COW image device as the last extent.
+    CreateLogicalPartitionParams cow_partition_params = params;
+    cow_partition_params.partition = nullptr;
+    cow_partition_params.partition_name = *cow_name;
+    cow_partition_params.device_name.clear();
+    DmTable table;
+    if (!CreateDmTable(cow_partition_params, &table)) {
+        return false;
+    }
+    // If the COW image exists, append it as the last extent.
+    if (snapshot_status.cow_file_size() > 0) {
+        std::string cow_image_device;
+        if (!dm.GetDeviceString(cow_image_name, &cow_image_device)) {
+            LOG(ERROR) << "Cannot determine major/minor for: " << cow_image_name;
+            return false;
+        }
+        auto cow_partition_sectors = snapshot_status.cow_partition_size() / kSectorSize;
+        auto cow_image_sectors = snapshot_status.cow_file_size() / kSectorSize;
+        table.Emplace<DmTargetLinear>(cow_partition_sectors, cow_image_sectors, cow_image_device,
+                                      0);
+    }
+
+    // We have created the DmTable now. Map it.
+    std::string cow_path;
+    if (!dm.CreateDevice(*cow_name, table, &cow_path, remaining_time)) {
+        LOG(ERROR) << "Could not create COW device: " << *cow_name;
+        return false;
+    }
+    created_devices->EmplaceBack<AutoUnmapDevice>(&dm, *cow_name);
+    LOG(INFO) << "Mapped COW device for " << params.GetPartitionName() << " at " << cow_path;
+    return true;
+}
+
+bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name) {
+    CHECK(lock);
+    if (!EnsureImageManager()) return false;
+
+    auto& dm = DeviceMapper::Instance();
+    auto cow_name = GetCowName(name);
+    if (!dm.DeleteDeviceIfExists(cow_name)) {
+        LOG(ERROR) << "Cannot unmap " << cow_name;
+        return false;
+    }
+
+    std::string cow_image_name = GetCowImageDeviceName(name);
+    if (!images_->UnmapImageIfExists(cow_image_name)) {
+        LOG(ERROR) << "Cannot unmap image " << cow_image_name;
+        return false;
+    }
+    return true;
+}
+
+auto SnapshotManager::OpenFile(const std::string& file, int lock_flags)
+        -> std::unique_ptr<LockedFile> {
+    unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+    if (fd < 0) {
+        PLOG(ERROR) << "Open failed: " << file;
+        return nullptr;
+    }
+    if (lock_flags != 0 && flock(fd, lock_flags) < 0) {
+        PLOG(ERROR) << "Acquire flock failed: " << file;
+        return nullptr;
+    }
+    // For simplicity, we want to CHECK that lock_mode == LOCK_EX, in some
+    // calls, so strip extra flags.
+    int lock_mode = lock_flags & (LOCK_EX | LOCK_SH);
+    return std::make_unique<LockedFile>(file, std::move(fd), lock_mode);
+}
+
+SnapshotManager::LockedFile::~LockedFile() {
+    if (flock(fd_, LOCK_UN) < 0) {
+        PLOG(ERROR) << "Failed to unlock file: " << path_;
+    }
+}
+
+std::string SnapshotManager::GetStateFilePath() const {
+    return metadata_dir_ + "/state"s;
+}
+
+std::string SnapshotManager::GetLockPath() const {
+    return metadata_dir_;
+}
+
+std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::OpenLock(int lock_flags) {
+    auto lock_file = GetLockPath();
+    return OpenFile(lock_file, lock_flags);
+}
+
+std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockShared() {
+    return OpenLock(LOCK_SH);
+}
+
+std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockExclusive() {
+    return OpenLock(LOCK_EX);
+}
+
+UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
+    CHECK(lock);
+
+    std::string contents;
+    if (!android::base::ReadFileToString(GetStateFilePath(), &contents)) {
+        PLOG(ERROR) << "Read state file failed";
+        return UpdateState::None;
+    }
+
+    if (contents.empty() || contents == "none") {
+        return UpdateState::None;
+    } else if (contents == "initiated") {
+        return UpdateState::Initiated;
+    } else if (contents == "unverified") {
+        return UpdateState::Unverified;
+    } else if (contents == "merging") {
+        return UpdateState::Merging;
+    } else if (contents == "merge-completed") {
+        return UpdateState::MergeCompleted;
+    } else if (contents == "merge-needs-reboot") {
+        return UpdateState::MergeNeedsReboot;
+    } else if (contents == "merge-failed") {
+        return UpdateState::MergeFailed;
+    } else {
+        LOG(ERROR) << "Unknown merge state in update state file";
+        return UpdateState::None;
+    }
+}
+
+std::ostream& operator<<(std::ostream& os, UpdateState state) {
+    switch (state) {
+        case UpdateState::None:
+            return os << "none";
+        case UpdateState::Initiated:
+            return os << "initiated";
+        case UpdateState::Unverified:
+            return os << "unverified";
+        case UpdateState::Merging:
+            return os << "merging";
+        case UpdateState::MergeCompleted:
+            return os << "merge-completed";
+        case UpdateState::MergeNeedsReboot:
+            return os << "merge-needs-reboot";
+        case UpdateState::MergeFailed:
+            return os << "merge-failed";
+        default:
+            LOG(ERROR) << "Unknown update state";
+            return os;
+    }
+}
+
+bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state) {
+    CHECK(lock);
+    CHECK(lock->lock_mode() == LOCK_EX);
+
+    std::stringstream ss;
+    ss << state;
+    std::string contents = ss.str();
+    if (contents.empty()) return false;
+
+#ifdef LIBSNAPSHOT_USE_HAL
+    auto merge_status = MergeStatus::UNKNOWN;
+    switch (state) {
+        // The needs-reboot and completed cases imply that /data and /metadata
+        // can be safely wiped, so we don't report a merge status.
+        case UpdateState::None:
+        case UpdateState::MergeNeedsReboot:
+        case UpdateState::MergeCompleted:
+        case UpdateState::Initiated:
+            merge_status = MergeStatus::NONE;
+            break;
+        case UpdateState::Unverified:
+            merge_status = MergeStatus::SNAPSHOTTED;
+            break;
+        case UpdateState::Merging:
+        case UpdateState::MergeFailed:
+            merge_status = MergeStatus::MERGING;
+            break;
+        default:
+            // Note that Cancelled flows to here - it is never written, since
+            // it only communicates a transient state to the caller.
+            LOG(ERROR) << "Unexpected update status: " << state;
+            break;
+    }
+
+    bool set_before_write =
+            merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING;
+    if (set_before_write && !device_->SetBootControlMergeStatus(merge_status)) {
+        return false;
+    }
+#endif
+
+    if (!WriteStringToFileAtomic(contents, GetStateFilePath())) {
+        PLOG(ERROR) << "Could not write to state file";
+        return false;
+    }
+
+#ifdef LIBSNAPSHOT_USE_HAL
+    if (!set_before_write && !device_->SetBootControlMergeStatus(merge_status)) {
+        return false;
+    }
+#endif
+    return true;
+}
+
+std::string SnapshotManager::GetSnapshotStatusFilePath(const std::string& name) {
+    auto file = metadata_dir_ + "/snapshots/"s + name;
+    return file;
+}
+
+bool SnapshotManager::ReadSnapshotStatus(LockedFile* lock, const std::string& name,
+                                         SnapshotStatus* status) {
+    CHECK(lock);
+    auto path = GetSnapshotStatusFilePath(name);
+
+    unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+    if (fd < 0) {
+        PLOG(ERROR) << "Open failed: " << path;
+        return false;
+    }
+
+    if (!status->ParseFromFileDescriptor(fd.get())) {
+        PLOG(ERROR) << "Unable to parse " << path << " as SnapshotStatus";
+        return false;
+    }
+
+    if (status->name() != name) {
+        LOG(WARNING) << "Found snapshot status named " << status->name() << " in " << path;
+        status->set_name(name);
+    }
+
+    return true;
+}
+
+bool SnapshotManager::WriteSnapshotStatus(LockedFile* lock, const SnapshotStatus& status) {
+    // The caller must take an exclusive lock to modify snapshots.
+    CHECK(lock);
+    CHECK(lock->lock_mode() == LOCK_EX);
+    CHECK(!status.name().empty());
+
+    auto path = GetSnapshotStatusFilePath(status.name());
+
+    std::string content;
+    if (!status.SerializeToString(&content)) {
+        LOG(ERROR) << "Unable to serialize SnapshotStatus for " << status.name();
+        return false;
+    }
+
+    if (!WriteStringToFileAtomic(content, path)) {
+        PLOG(ERROR) << "Unable to write SnapshotStatus to " << path;
+        return false;
+    }
+
+    return true;
+}
+
+std::string SnapshotManager::GetSnapshotDeviceName(const std::string& snapshot_name,
+                                                   const SnapshotStatus& status) {
+    if (status.device_size() != status.snapshot_size()) {
+        return GetSnapshotExtraDeviceName(snapshot_name);
+    }
+    return snapshot_name;
+}
+
+bool SnapshotManager::EnsureImageManager() {
+    if (images_) return true;
+
+    // For now, use a preset timeout.
+    images_ = android::fiemap::IImageManager::Open(gsid_dir_, 15000ms);
+    if (!images_) {
+        LOG(ERROR) << "Could not open ImageManager";
+        return false;
+    }
+    return true;
+}
+
+bool SnapshotManager::ForceLocalImageManager() {
+    images_ = android::fiemap::ImageManager::Open(gsid_dir_);
+    if (!images_) {
+        LOG(ERROR) << "Could not open ImageManager";
+        return false;
+    }
+    has_local_image_manager_ = true;
+    return true;
+}
+
+static void UnmapAndDeleteCowPartition(MetadataBuilder* current_metadata) {
+    auto& dm = DeviceMapper::Instance();
+    std::vector<std::string> to_delete;
+    for (auto* existing_cow_partition : current_metadata->ListPartitionsInGroup(kCowGroupName)) {
+        if (!dm.DeleteDeviceIfExists(existing_cow_partition->name())) {
+            LOG(WARNING) << existing_cow_partition->name()
+                         << " cannot be unmapped and its space cannot be reclaimed";
+            continue;
+        }
+        to_delete.push_back(existing_cow_partition->name());
+    }
+    for (const auto& name : to_delete) {
+        current_metadata->RemovePartition(name);
+    }
+}
+
+bool SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) {
+    auto lock = LockExclusive();
+    if (!lock) return false;
+
+    // TODO(b/134949511): remove this check. Right now, with overlayfs mounted, the scratch
+    // partition takes up a big chunk of space in super, causing COW images to be created on
+    // retrofit Virtual A/B devices.
+    if (device_->IsOverlayfsSetup()) {
+        LOG(ERROR) << "Cannot create update snapshots with overlayfs setup. Run `adb enable-verity`"
+                   << ", reboot, then try again.";
+        return false;
+    }
+
+    const auto& opener = device_->GetPartitionOpener();
+    auto current_suffix = device_->GetSlotSuffix();
+    uint32_t current_slot = SlotNumberForSlotSuffix(current_suffix);
+    auto target_suffix = device_->GetOtherSlotSuffix();
+    uint32_t target_slot = SlotNumberForSlotSuffix(target_suffix);
+    auto current_super = device_->GetSuperDevice(current_slot);
+
+    auto current_metadata = MetadataBuilder::New(opener, current_super, current_slot);
+    auto target_metadata =
+            MetadataBuilder::NewForUpdate(opener, current_super, current_slot, target_slot);
+
+    // Delete partitions with target suffix in |current_metadata|. Otherwise,
+    // partition_cow_creator recognizes these left-over partitions as used space.
+    for (const auto& group_name : current_metadata->ListGroups()) {
+        if (android::base::EndsWith(group_name, target_suffix)) {
+            current_metadata->RemoveGroupAndPartitions(group_name);
+        }
+    }
+
+    SnapshotMetadataUpdater metadata_updater(target_metadata.get(), target_slot, manifest);
+    if (!metadata_updater.Update()) {
+        LOG(ERROR) << "Cannot calculate new metadata.";
+        return false;
+    }
+
+    // Delete previous COW partitions in current_metadata so that PartitionCowCreator marks those as
+    // free regions.
+    UnmapAndDeleteCowPartition(current_metadata.get());
+
+    // Check that all these metadata is not retrofit dynamic partitions. Snapshots on
+    // devices with retrofit dynamic partitions does not make sense.
+    // This ensures that current_metadata->GetFreeRegions() uses the same device
+    // indices as target_metadata (i.e. 0 -> "super").
+    // This is also assumed in MapCowDevices() call below.
+    CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
+          target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME);
+
+    std::map<std::string, SnapshotStatus> all_snapshot_status;
+
+    // In case of error, automatically delete devices that are created along the way.
+    // Note that "lock" is destroyed after "created_devices", so it is safe to use |lock| for
+    // these devices.
+    AutoDeviceList created_devices;
+
+    PartitionCowCreator cow_creator{
+            .target_metadata = target_metadata.get(),
+            .target_suffix = target_suffix,
+            .target_partition = nullptr,
+            .current_metadata = current_metadata.get(),
+            .current_suffix = current_suffix,
+            .operations = nullptr,
+            .extra_extents = {},
+    };
+
+    if (!CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
+                                       &all_snapshot_status)) {
+        return false;
+    }
+
+    auto exported_target_metadata = target_metadata->Export();
+    if (exported_target_metadata == nullptr) {
+        LOG(ERROR) << "Cannot export target metadata";
+        return false;
+    }
+
+    if (!InitializeUpdateSnapshots(lock.get(), target_metadata.get(),
+                                   exported_target_metadata.get(), target_suffix,
+                                   all_snapshot_status)) {
+        return false;
+    }
+
+    if (!UpdatePartitionTable(opener, device_->GetSuperDevice(target_slot),
+                              *exported_target_metadata, target_slot)) {
+        LOG(ERROR) << "Cannot write target metadata";
+        return false;
+    }
+
+    created_devices.Release();
+    LOG(INFO) << "Successfully created all snapshots for target slot " << target_suffix;
+
+    return true;
+}
+
+bool SnapshotManager::CreateUpdateSnapshotsInternal(
+        LockedFile* lock, const DeltaArchiveManifest& manifest, PartitionCowCreator* cow_creator,
+        AutoDeviceList* created_devices,
+        std::map<std::string, SnapshotStatus>* all_snapshot_status) {
+    CHECK(lock);
+
+    auto* target_metadata = cow_creator->target_metadata;
+    const auto& target_suffix = cow_creator->target_suffix;
+
+    if (!target_metadata->AddGroup(kCowGroupName, 0)) {
+        LOG(ERROR) << "Cannot add group " << kCowGroupName;
+        return false;
+    }
+
+    std::map<std::string, const RepeatedPtrField<InstallOperation>*> install_operation_map;
+    std::map<std::string, std::vector<Extent>> extra_extents_map;
+    for (const auto& partition_update : manifest.partitions()) {
+        auto suffixed_name = partition_update.partition_name() + target_suffix;
+        auto&& [it, inserted] =
+                install_operation_map.emplace(suffixed_name, &partition_update.operations());
+        if (!inserted) {
+            LOG(ERROR) << "Duplicated partition " << partition_update.partition_name()
+                       << " in update manifest.";
+            return false;
+        }
+
+        auto& extra_extents = extra_extents_map[suffixed_name];
+        if (partition_update.has_hash_tree_extent()) {
+            extra_extents.push_back(partition_update.hash_tree_extent());
+        }
+        if (partition_update.has_fec_extent()) {
+            extra_extents.push_back(partition_update.fec_extent());
+        }
+    }
+
+    for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) {
+        cow_creator->target_partition = target_partition;
+        cow_creator->operations = nullptr;
+        auto operations_it = install_operation_map.find(target_partition->name());
+        if (operations_it != install_operation_map.end()) {
+            cow_creator->operations = operations_it->second;
+        }
+
+        cow_creator->extra_extents.clear();
+        auto extra_extents_it = extra_extents_map.find(target_partition->name());
+        if (extra_extents_it != extra_extents_map.end()) {
+            cow_creator->extra_extents = std::move(extra_extents_it->second);
+        }
+
+        // Compute the device sizes for the partition.
+        auto cow_creator_ret = cow_creator->Run();
+        if (!cow_creator_ret.has_value()) {
+            return false;
+        }
+
+        LOG(INFO) << "For partition " << target_partition->name()
+                  << ", device size = " << cow_creator_ret->snapshot_status.device_size()
+                  << ", snapshot size = " << cow_creator_ret->snapshot_status.snapshot_size()
+                  << ", cow partition size = "
+                  << cow_creator_ret->snapshot_status.cow_partition_size()
+                  << ", cow file size = " << cow_creator_ret->snapshot_status.cow_file_size();
+
+        // Delete any existing snapshot before re-creating one.
+        if (!DeleteSnapshot(lock, target_partition->name())) {
+            LOG(ERROR) << "Cannot delete existing snapshot before creating a new one for partition "
+                       << target_partition->name();
+            return false;
+        }
+
+        // It is possible that the whole partition uses free space in super, and snapshot / COW
+        // would not be needed. In this case, skip the partition.
+        bool needs_snapshot = cow_creator_ret->snapshot_status.snapshot_size() > 0;
+        bool needs_cow = (cow_creator_ret->snapshot_status.cow_partition_size() +
+                          cow_creator_ret->snapshot_status.cow_file_size()) > 0;
+        CHECK(needs_snapshot == needs_cow);
+
+        if (!needs_snapshot) {
+            LOG(INFO) << "Skip creating snapshot for partition " << target_partition->name()
+                      << "because nothing needs to be snapshotted.";
+            continue;
+        }
+
+        // Store these device sizes to snapshot status file.
+        if (!CreateSnapshot(lock, &cow_creator_ret->snapshot_status)) {
+            return false;
+        }
+        created_devices->EmplaceBack<AutoDeleteSnapshot>(this, lock, target_partition->name());
+
+        // Create the COW partition. That is, use any remaining free space in super partition before
+        // creating the COW images.
+        if (cow_creator_ret->snapshot_status.cow_partition_size() > 0) {
+            CHECK(cow_creator_ret->snapshot_status.cow_partition_size() % kSectorSize == 0)
+                    << "cow_partition_size == "
+                    << cow_creator_ret->snapshot_status.cow_partition_size()
+                    << " is not a multiple of sector size " << kSectorSize;
+            auto cow_partition = target_metadata->AddPartition(GetCowName(target_partition->name()),
+                                                               kCowGroupName, 0 /* flags */);
+            if (cow_partition == nullptr) {
+                return false;
+            }
+
+            if (!target_metadata->ResizePartition(
+                        cow_partition, cow_creator_ret->snapshot_status.cow_partition_size(),
+                        cow_creator_ret->cow_partition_usable_regions)) {
+                LOG(ERROR) << "Cannot create COW partition on metadata with size "
+                           << cow_creator_ret->snapshot_status.cow_partition_size();
+                return false;
+            }
+            // Only the in-memory target_metadata is modified; nothing to clean up if there is an
+            // error in the future.
+        }
+
+        // Create the backing COW image if necessary.
+        if (cow_creator_ret->snapshot_status.cow_file_size() > 0) {
+            if (!CreateCowImage(lock, target_partition->name())) {
+                return false;
+            }
+        }
+
+        all_snapshot_status->emplace(target_partition->name(),
+                                     std::move(cow_creator_ret->snapshot_status));
+
+        LOG(INFO) << "Successfully created snapshot for " << target_partition->name();
+    }
+    return true;
+}
+
+bool SnapshotManager::InitializeUpdateSnapshots(
+        LockedFile* lock, MetadataBuilder* target_metadata,
+        const LpMetadata* exported_target_metadata, const std::string& target_suffix,
+        const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
+    CHECK(lock);
+
+    auto& dm = DeviceMapper::Instance();
+    CreateLogicalPartitionParams cow_params{
+            .block_device = LP_METADATA_DEFAULT_PARTITION_NAME,
+            .metadata = exported_target_metadata,
+            .timeout_ms = std::chrono::milliseconds::max(),
+            .partition_opener = &device_->GetPartitionOpener(),
+    };
+    for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) {
+        AutoDeviceList created_devices_for_cow;
+
+        if (!UnmapPartitionWithSnapshot(lock, target_partition->name())) {
+            LOG(ERROR) << "Cannot unmap existing COW devices before re-mapping them for zero-fill: "
+                       << target_partition->name();
+            return false;
+        }
+
+        auto it = all_snapshot_status.find(target_partition->name());
+        if (it == all_snapshot_status.end()) continue;
+        cow_params.partition_name = target_partition->name();
+        std::string cow_name;
+        if (!MapCowDevices(lock, cow_params, it->second, &created_devices_for_cow, &cow_name)) {
+            return false;
+        }
+
+        std::string cow_path;
+        if (!dm.GetDmDevicePathByName(cow_name, &cow_path)) {
+            LOG(ERROR) << "Cannot determine path for " << cow_name;
+            return false;
+        }
+
+        if (!InitializeCow(cow_path)) {
+            LOG(ERROR) << "Can't zero-fill COW device for " << target_partition->name() << ": "
+                       << cow_path;
+            return false;
+        }
+        // Let destructor of created_devices_for_cow to unmap the COW devices.
+    };
+    return true;
+}
+
+bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& params,
+                                        std::string* snapshot_path) {
+    auto lock = LockShared();
+    if (!lock) return false;
+    if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) {
+        LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: "
+                   << params.GetPartitionName();
+        return false;
+    }
+    return MapPartitionWithSnapshot(lock.get(), params, snapshot_path);
+}
+
+bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) {
+    auto lock = LockShared();
+    if (!lock) return false;
+    return UnmapPartitionWithSnapshot(lock.get(), target_partition_name);
+}
+
+bool SnapshotManager::UnmapAllPartitions() {
+    auto lock = LockExclusive();
+    if (!lock) return false;
+
+    const auto& opener = device_->GetPartitionOpener();
+    uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
+    auto super_device = device_->GetSuperDevice(slot);
+    auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
+    if (!metadata) {
+        LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
+        return false;
+    }
+
+    bool ok = true;
+    for (const auto& partition : metadata->partitions) {
+        auto partition_name = GetPartitionName(partition);
+        ok &= UnmapPartitionWithSnapshot(lock.get(), partition_name);
+    }
+    return ok;
+}
+
+std::ostream& operator<<(std::ostream& os, SnapshotManager::Slot slot) {
+    switch (slot) {
+        case SnapshotManager::Slot::Unknown:
+            return os << "unknown";
+        case SnapshotManager::Slot::Source:
+            return os << "source";
+        case SnapshotManager::Slot::Target:
+            return os << "target";
+    }
+}
+
+bool SnapshotManager::Dump(std::ostream& os) {
+    // Don't actually lock. Dump() is for debugging purposes only, so it is okay
+    // if it is racy.
+    auto file = OpenLock(0 /* lock flag */);
+    if (!file) return false;
+
+    std::stringstream ss;
+
+    ss << "Update state: " << ReadUpdateState(file.get()) << std::endl;
+
+    ss << "Current slot: " << device_->GetSlotSuffix() << std::endl;
+    ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl;
+
+    bool ok = true;
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(file.get(), &snapshots)) {
+        LOG(ERROR) << "Could not list snapshots";
+        snapshots.clear();
+        ok = false;
+    }
+    for (const auto& name : snapshots) {
+        ss << "Snapshot: " << name << std::endl;
+        SnapshotStatus status;
+        if (!ReadSnapshotStatus(file.get(), name, &status)) {
+            ok = false;
+            continue;
+        }
+        ss << "    state: " << SnapshotState_Name(status.state()) << std::endl;
+        ss << "    device size (bytes): " << status.device_size() << std::endl;
+        ss << "    snapshot size (bytes): " << status.snapshot_size() << std::endl;
+        ss << "    cow partition size (bytes): " << status.cow_partition_size() << std::endl;
+        ss << "    cow file size (bytes): " << status.cow_file_size() << std::endl;
+        ss << "    allocated sectors: " << status.sectors_allocated() << std::endl;
+        ss << "    metadata sectors: " << status.metadata_sectors() << std::endl;
+    }
+    os << ss.rdbuf();
+    return ok;
+}
+
+std::unique_ptr<AutoDevice> SnapshotManager::EnsureMetadataMounted() {
+    if (!device_->IsRecovery()) {
+        // No need to mount anything in recovery.
+        LOG(INFO) << "EnsureMetadataMounted does nothing in Android mode.";
+        return std::unique_ptr<AutoUnmountDevice>(new AutoUnmountDevice());
+    }
+    return AutoUnmountDevice::New(device_->GetMetadataDir());
+}
+
+UpdateState SnapshotManager::InitiateMergeAndWait() {
+    {
+        auto lock = LockExclusive();
+        // Sync update state from file with bootloader.
+        if (!WriteUpdateState(lock.get(), ReadUpdateState(lock.get()))) {
+            LOG(WARNING) << "Unable to sync write update state, fastboot may "
+                         << "reject / accept wipes incorrectly!";
+        }
+    }
+
+    LOG(INFO) << "Waiting for any previous merge request to complete. "
+              << "This can take up to several minutes.";
+    auto state = ProcessUpdateState();
+    if (state == UpdateState::None) {
+        LOG(INFO) << "Can't find any snapshot to merge.";
+        return state;
+    }
+    if (state == UpdateState::Unverified) {
+        if (!InitiateMerge()) {
+            LOG(ERROR) << "Failed to initiate merge.";
+            return state;
+        }
+        // All other states can be handled by ProcessUpdateState.
+        LOG(INFO) << "Waiting for merge to complete. This can take up to several minutes.";
+        state = ProcessUpdateState();
+    }
+
+    LOG(INFO) << "Merge finished with state \"" << state << "\".";
+    return state;
+}
+
+bool SnapshotManager::WaitForMerge() {
+    LOG(INFO) << "Waiting for any previous merge request to complete. "
+              << "This can take up to several minutes.";
+    while (true) {
+        auto state = ProcessUpdateState();
+        if (state == UpdateState::Unverified && GetCurrentSlot() == Slot::Target) {
+            LOG(INFO) << "Wait for merge to be initiated.";
+            std::this_thread::sleep_for(kUpdateStateCheckInterval);
+            continue;
+        }
+        LOG(INFO) << "Wait for merge exits with state " << state;
+        return state == UpdateState::None || state == UpdateState::MergeCompleted;
+    }
+}
+
+bool SnapshotManager::HandleImminentDataWipe(const std::function<void()>& callback) {
+    if (!device_->IsRecovery()) {
+        LOG(ERROR) << "Data wipes are only allowed in recovery.";
+        return false;
+    }
+
+    auto mount = EnsureMetadataMounted();
+    if (!mount || !mount->HasDevice()) {
+        // We allow the wipe to continue, because if we can't mount /metadata,
+        // it is unlikely the device would have booted anyway. If there is no
+        // metadata partition, then the device predates Virtual A/B.
+        return true;
+    }
+
+    // Check this early, so we don't accidentally start trying to populate
+    // the state file in recovery. Note we don't call GetUpdateState since
+    // we want errors in acquiring the lock to be propagated, instead of
+    // returning UpdateState::None.
+    auto state_file = GetStateFilePath();
+    if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
+        return true;
+    }
+
+    auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
+    auto super_path = device_->GetSuperDevice(slot_number);
+    if (!CreateLogicalAndSnapshotPartitions(super_path)) {
+        LOG(ERROR) << "Unable to map partitions to complete merge.";
+        return false;
+    }
+
+    UpdateState state = ProcessUpdateState(callback);
+    LOG(INFO) << "Update state in recovery: " << state;
+    switch (state) {
+        case UpdateState::MergeFailed:
+            LOG(ERROR) << "Unrecoverable merge failure detected.";
+            return false;
+        case UpdateState::Unverified: {
+            // If an OTA was just applied but has not yet started merging, we
+            // have no choice but to revert slots, because the current slot will
+            // immediately become unbootable. Rather than wait for the device
+            // to reboot N times until a rollback, we proactively disable the
+            // new slot instead.
+            //
+            // Since the rollback is inevitable, we don't treat a HAL failure
+            // as an error here.
+            auto slot = GetCurrentSlot();
+            if (slot == Slot::Target) {
+                LOG(ERROR) << "Reverting to old slot since update will be deleted.";
+                device_->SetSlotAsUnbootable(slot_number);
+            }
+            break;
+        }
+        case UpdateState::MergeNeedsReboot:
+            // We shouldn't get here, because nothing is depending on
+            // logical partitions.
+            LOG(ERROR) << "Unexpected merge-needs-reboot state in recovery.";
+            break;
+        default:
+            break;
+    }
+
+    // Nothing should be depending on partitions now, so unmap them all.
+    if (!UnmapAllPartitions()) {
+        LOG(ERROR) << "Unable to unmap all partitions; fastboot may fail to flash.";
+    }
+    return true;
+}
+
+bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
+    CHECK(lock);
+
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(lock, &snapshots)) {
+        LOG(ERROR) << "Could not list snapshots.";
+        return false;
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    for (const auto& snapshot : snapshots) {
+        std::vector<DeviceMapper::TargetInfo> targets;
+        if (!dm.GetTableStatus(snapshot, &targets)) {
+            LOG(ERROR) << "Could not read snapshot device table: " << snapshot;
+            return false;
+        }
+        if (targets.size() != 1) {
+            LOG(ERROR) << "Unexpected device-mapper table for snapshot: " << snapshot
+                       << ", size = " << targets.size();
+            return false;
+        }
+        if (targets[0].IsOverflowSnapshot()) {
+            LOG(ERROR) << "Detected overflow in snapshot " << snapshot
+                       << ", CoW device size computation is wrong!";
+            return false;
+        }
+    }
+
+    return true;
+}
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp b/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp
new file mode 100644
index 0000000..60bf796
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp
@@ -0,0 +1,273 @@
+//
+// 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 "snapshot_metadata_updater.h"
+
+#include <algorithm>
+#include <map>
+#include <optional>
+#include <set>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fs_mgr.h>
+#include <libsnapshot/snapshot.h>
+
+using android::fs_mgr::MetadataBuilder;
+using android::fs_mgr::Partition;
+using android::fs_mgr::SlotSuffixForSlotNumber;
+using chromeos_update_engine::DeltaArchiveManifest;
+
+namespace android {
+namespace snapshot {
+SnapshotMetadataUpdater::SnapshotMetadataUpdater(MetadataBuilder* builder, uint32_t target_slot,
+                                                 const DeltaArchiveManifest& manifest)
+    : builder_(builder), target_suffix_(SlotSuffixForSlotNumber(target_slot)) {
+    if (!manifest.has_dynamic_partition_metadata()) {
+        return;
+    }
+
+    // Key: partition name ("system"). Value: group name ("group").
+    // No suffix.
+    std::map<std::string_view, std::string_view> partition_group_map;
+    const auto& metadata_groups = manifest.dynamic_partition_metadata().groups();
+    groups_.reserve(metadata_groups.size());
+    for (const auto& group : metadata_groups) {
+        groups_.emplace_back(Group{group.name() + target_suffix_, &group});
+        for (const auto& partition_name : group.partition_names()) {
+            partition_group_map[partition_name] = group.name();
+        }
+    }
+
+    for (const auto& p : manifest.partitions()) {
+        auto it = partition_group_map.find(p.partition_name());
+        if (it != partition_group_map.end()) {
+            partitions_.emplace_back(Partition{p.partition_name() + target_suffix_,
+                                               std::string(it->second) + target_suffix_, &p});
+        }
+    }
+}
+
+bool SnapshotMetadataUpdater::ShrinkPartitions() const {
+    for (const auto& partition_update : partitions_) {
+        auto* existing_partition = builder_->FindPartition(partition_update.name);
+        if (existing_partition == nullptr) {
+            continue;
+        }
+        auto new_size = partition_update->new_partition_info().size();
+        if (existing_partition->size() <= new_size) {
+            continue;
+        }
+        if (!builder_->ResizePartition(existing_partition, new_size)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::DeletePartitions() const {
+    std::vector<std::string> partitions_to_delete;
+    // Don't delete partitions in groups where the group name doesn't have target_suffix,
+    // e.g. default.
+    for (auto* existing_partition : ListPartitionsWithSuffix(builder_, target_suffix_)) {
+        auto iter = std::find_if(partitions_.begin(), partitions_.end(),
+                                 [existing_partition](auto&& partition_update) {
+                                     return partition_update.name == existing_partition->name();
+                                 });
+        // Update package metadata doesn't have this partition. Prepare to delete it.
+        // Not deleting from builder_ yet because it may break ListPartitionsWithSuffix if it were
+        // to return an iterable view of builder_.
+        if (iter == partitions_.end()) {
+            partitions_to_delete.push_back(existing_partition->name());
+        }
+    }
+
+    for (const auto& partition_name : partitions_to_delete) {
+        builder_->RemovePartition(partition_name);
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::MovePartitionsToDefault() const {
+    for (const auto& partition_update : partitions_) {
+        auto* existing_partition = builder_->FindPartition(partition_update.name);
+        if (existing_partition == nullptr) {
+            continue;
+        }
+        if (existing_partition->group_name() == partition_update.group_name) {
+            continue;
+        }
+        // Move to "default" group (which doesn't have maximum size constraint)
+        // temporarily.
+        if (!builder_->ChangePartitionGroup(existing_partition, android::fs_mgr::kDefaultGroup)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::ShrinkGroups() const {
+    for (const auto& group_update : groups_) {
+        auto* existing_group = builder_->FindGroup(group_update.name);
+        if (existing_group == nullptr) {
+            continue;
+        }
+        if (existing_group->maximum_size() <= group_update->size()) {
+            continue;
+        }
+        if (!builder_->ChangeGroupSize(existing_group->name(), group_update->size())) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::DeleteGroups() const {
+    std::vector<std::string> existing_groups = builder_->ListGroups();
+    for (const auto& existing_group_name : existing_groups) {
+        // Don't delete groups without target suffix, e.g. default.
+        if (!android::base::EndsWith(existing_group_name, target_suffix_)) {
+            continue;
+        }
+
+        auto iter = std::find_if(groups_.begin(), groups_.end(),
+                                 [&existing_group_name](auto&& group_update) {
+                                     return group_update.name == existing_group_name;
+                                 });
+        // Update package metadata has this group as well, so not deleting it.
+        if (iter != groups_.end()) {
+            continue;
+        }
+        // Update package metadata doesn't have this group. Before deleting it, sanity check that it
+        // doesn't have any partitions left. Update metadata shouldn't assign any partitions to this
+        // group, so all partitions that originally belong to this group should be moved by
+        // MovePartitionsToDefault at this point.
+        auto existing_partitions_in_group = builder_->ListPartitionsInGroup(existing_group_name);
+        if (!existing_partitions_in_group.empty()) {
+            std::vector<std::string> partition_names_in_group;
+            std::transform(existing_partitions_in_group.begin(), existing_partitions_in_group.end(),
+                           std::back_inserter(partition_names_in_group),
+                           [](auto* p) { return p->name(); });
+            LOG(ERROR)
+                    << "Group " << existing_group_name
+                    << " cannot be deleted because the following partitions are left unassigned: ["
+                    << android::base::Join(partition_names_in_group, ",") << "]";
+            return false;
+        }
+        builder_->RemoveGroupAndPartitions(existing_group_name);
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::AddGroups() const {
+    for (const auto& group_update : groups_) {
+        if (builder_->FindGroup(group_update.name) == nullptr) {
+            if (!builder_->AddGroup(group_update.name, group_update->size())) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::GrowGroups() const {
+    for (const auto& group_update : groups_) {
+        auto* existing_group = builder_->FindGroup(group_update.name);
+        if (existing_group == nullptr) {
+            continue;
+        }
+        if (existing_group->maximum_size() >= group_update->size()) {
+            continue;
+        }
+        if (!builder_->ChangeGroupSize(existing_group->name(), group_update->size())) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::AddPartitions() const {
+    for (const auto& partition_update : partitions_) {
+        if (builder_->FindPartition(partition_update.name) == nullptr) {
+            auto* p =
+                    builder_->AddPartition(partition_update.name, partition_update.group_name,
+                                           LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_UPDATED);
+            if (p == nullptr) {
+                return false;
+            }
+        }
+    }
+    // Will be resized in GrowPartitions.
+    return true;
+}
+
+bool SnapshotMetadataUpdater::GrowPartitions() const {
+    for (const auto& partition_update : partitions_) {
+        auto* existing_partition = builder_->FindPartition(partition_update.name);
+        if (existing_partition == nullptr) {
+            continue;
+        }
+        auto new_size = partition_update->new_partition_info().size();
+        if (existing_partition->size() >= new_size) {
+            continue;
+        }
+        if (!builder_->ResizePartition(existing_partition, new_size)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::MovePartitionsToCorrectGroup() const {
+    for (const auto& partition_update : partitions_) {
+        auto* existing_partition = builder_->FindPartition(partition_update.name);
+        if (existing_partition == nullptr) {
+            continue;
+        }
+        if (existing_partition->group_name() == partition_update.group_name) {
+            continue;
+        }
+        if (!builder_->ChangePartitionGroup(existing_partition, partition_update.group_name)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SnapshotMetadataUpdater::Update() const {
+    // Remove extents used by COW devices by removing the COW group completely.
+    builder_->RemoveGroupAndPartitions(android::snapshot::kCowGroupName);
+
+    // The order of these operations are important so that we
+    // always have enough space to grow or add new partitions / groups.
+    // clang-format off
+    return ShrinkPartitions() &&
+           DeletePartitions() &&
+           MovePartitionsToDefault() &&
+           ShrinkGroups() &&
+           DeleteGroups() &&
+           AddGroups() &&
+           GrowGroups() &&
+           AddPartitions() &&
+           GrowPartitions() &&
+           MovePartitionsToCorrectGroup();
+    // clang-format on
+}
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_metadata_updater.h b/fs_mgr/libsnapshot/snapshot_metadata_updater.h
new file mode 100644
index 0000000..83c9460
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_metadata_updater.h
@@ -0,0 +1,85 @@
+//
+// 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 <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <liblp/builder.h>
+#include <update_engine/update_metadata.pb.h>
+
+#include "utility.h"
+
+namespace android {
+namespace snapshot {
+
+// Helper class that modifies a super partition metadata for an update for
+// Virtual A/B devices.
+class SnapshotMetadataUpdater {
+    using DeltaArchiveManifest = chromeos_update_engine::DeltaArchiveManifest;
+    using DynamicPartitionMetadata = chromeos_update_engine::DynamicPartitionMetadata;
+    using DynamicPartitionGroup = chromeos_update_engine::DynamicPartitionGroup;
+    using PartitionUpdate = chromeos_update_engine::PartitionUpdate;
+
+  public:
+    // Caller is responsible for ensuring the lifetime of manifest to be longer
+    // than SnapshotMetadataUpdater.
+    SnapshotMetadataUpdater(android::fs_mgr::MetadataBuilder* builder, uint32_t target_slot,
+                            const DeltaArchiveManifest& manifest);
+    bool Update() const;
+
+  private:
+    bool RenameGroupSuffix() const;
+    bool ShrinkPartitions() const;
+    bool DeletePartitions() const;
+    bool MovePartitionsToDefault() const;
+    bool ShrinkGroups() const;
+    bool DeleteGroups() const;
+    bool AddGroups() const;
+    bool GrowGroups() const;
+    bool AddPartitions() const;
+    bool GrowPartitions() const;
+    bool MovePartitionsToCorrectGroup() const;
+
+    // Wraps a DynamicPartitionGroup with a slot-suffixed name. Always use
+    // .name instead of ->name() because .name has the slot suffix (e.g.
+    // .name is "group_b" and ->name() is "group".)
+    struct Group {
+        std::string name;
+        const DynamicPartitionGroup* group;
+        const DynamicPartitionGroup* operator->() const { return group; }
+    };
+    // Wraps a PartitionUpdate with a slot-suffixed name / group name. Always use
+    // .name instead of ->partition_name() because .name has the slot suffix (e.g.
+    // .name is "system_b" and ->partition_name() is "system".)
+    struct Partition {
+        std::string name;
+        std::string group_name;
+        const PartitionUpdate* partition;
+        const PartitionUpdate* operator->() const { return partition; }
+    };
+
+    android::fs_mgr::MetadataBuilder* const builder_;
+    const std::string target_suffix_;
+    std::vector<Group> groups_;
+    std::vector<Partition> partitions_;
+};
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp b/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp
new file mode 100644
index 0000000..337be4f
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_metadata_updater_test.cpp
@@ -0,0 +1,331 @@
+//
+// 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 "snapshot_metadata_updater.h"
+
+#include <memory>
+#include <string>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <liblp/builder.h>
+#include <storage_literals/storage_literals.h>
+
+#include <libsnapshot/test_helpers.h>
+
+using namespace android::storage_literals;
+using android::fs_mgr::LpMetadata;
+using android::fs_mgr::MetadataBuilder;
+using android::fs_mgr::SlotSuffixForSlotNumber;
+using chromeos_update_engine::DeltaArchiveManifest;
+using chromeos_update_engine::DynamicPartitionGroup;
+using chromeos_update_engine::PartitionUpdate;
+using testing::AssertionFailure;
+using testing::AssertionResult;
+using testing::AssertionSuccess;
+
+namespace android {
+namespace snapshot {
+
+class SnapshotMetadataUpdaterTest : public ::testing::TestWithParam<uint32_t> {
+  public:
+    void SetUp() override {
+        target_slot_ = GetParam();
+        target_suffix_ = SlotSuffixForSlotNumber(target_slot_);
+        SnapshotTestPropertyFetcher::SetUp(SlotSuffixForSlotNumber(1 - target_slot_));
+        builder_ = MetadataBuilder::New(4_GiB + 1_MiB, 4_KiB, 2);
+
+        group_ = manifest_.mutable_dynamic_partition_metadata()->add_groups();
+        group_->set_name("group");
+        group_->set_size(4_GiB);
+        group_->add_partition_names("system");
+        group_->add_partition_names("vendor");
+        system_ = manifest_.add_partitions();
+        system_->set_partition_name("system");
+        SetSize(system_, 2_GiB);
+        vendor_ = manifest_.add_partitions();
+        vendor_->set_partition_name("vendor");
+        SetSize(vendor_, 1_GiB);
+
+        ASSERT_TRUE(FillFakeMetadata(builder_.get(), manifest_, target_suffix_));
+    }
+
+    void TearDown() override { SnapshotTestPropertyFetcher::TearDown(); }
+
+    // Append suffix to name.
+    std::string T(std::string_view name) { return std::string(name) + target_suffix_; }
+
+    AssertionResult UpdateAndExport() {
+        SnapshotMetadataUpdater updater(builder_.get(), target_slot_, manifest_);
+        if (!updater.Update()) {
+            return AssertionFailure() << "Update failed.";
+        }
+
+        exported_ = builder_->Export();
+        if (exported_ == nullptr) {
+            return AssertionFailure() << "Export failed.";
+        }
+        return AssertionSuccess();
+    }
+
+    // Check that in |builder_|, partition |name| + |target_suffix_| has the given |size|.
+    AssertionResult CheckSize(std::string_view name, uint64_t size) {
+        auto p = builder_->FindPartition(T(name));
+        if (p == nullptr) {
+            return AssertionFailure() << "Cannot find partition " << T(name);
+        }
+        if (p->size() != size) {
+            return AssertionFailure() << "Partition " << T(name) << " should be " << size
+                                      << " bytes, but is " << p->size() << " bytes.";
+        }
+        return AssertionSuccess() << "Partition" << T(name) << " is " << size << " bytes.";
+    }
+
+    // Check that in |builder_|, group |name| + |target_suffix_| has the given |size|.
+    AssertionResult CheckGroupSize(std::string_view name, uint64_t size) {
+        auto g = builder_->FindGroup(T(name));
+        if (g == nullptr) {
+            return AssertionFailure() << "Cannot find group " << T(name);
+        }
+        if (g->maximum_size() != size) {
+            return AssertionFailure() << "Group " << T(name) << " should be " << size
+                                      << " bytes, but is " << g->maximum_size() << " bytes.";
+        }
+        return AssertionSuccess() << "Group" << T(name) << " is " << size << " bytes.";
+    }
+
+    // Check that in |builder_|, partition |partition_name| + |target_suffix_| is in group
+    // |group_name| + |target_suffix_|;
+    AssertionResult CheckGroupName(std::string_view partition_name, std::string_view group_name) {
+        auto p = builder_->FindPartition(T(partition_name));
+        if (p == nullptr) {
+            return AssertionFailure() << "Cannot find partition " << T(partition_name);
+        }
+        if (p->group_name() != T(group_name)) {
+            return AssertionFailure() << "Partition " << T(partition_name) << " should be in "
+                                      << T(group_name) << ", but is in " << p->group_name() << ".";
+        }
+        return AssertionSuccess() << "Partition" << T(partition_name) << " is in " << T(group_name)
+                                  << ".";
+    }
+
+    std::unique_ptr<MetadataBuilder> builder_;
+    uint32_t target_slot_;
+    std::string target_suffix_;
+    DeltaArchiveManifest manifest_;
+    std::unique_ptr<LpMetadata> exported_;
+    DynamicPartitionGroup* group_ = nullptr;
+    PartitionUpdate* system_ = nullptr;
+    PartitionUpdate* vendor_ = nullptr;
+};
+
+TEST_P(SnapshotMetadataUpdaterTest, NoChange) {
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckGroupSize("group", 4_GiB));
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_TRUE(CheckGroupName("system", "group"));
+    EXPECT_TRUE(CheckSize("vendor", 1_GiB));
+    EXPECT_TRUE(CheckGroupName("vendor", "group"));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, GrowWithinBounds) {
+    SetSize(system_, 2_GiB + 512_MiB);
+    SetSize(vendor_, 1_GiB + 512_MiB);
+
+    ASSERT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 2_GiB + 512_MiB));
+    EXPECT_TRUE(CheckSize("vendor", 1_GiB + 512_MiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, GrowOverSuper) {
+    SetSize(system_, 3_GiB);
+    SetSize(vendor_, 1_GiB + 512_MiB);
+
+    EXPECT_FALSE(UpdateAndExport());
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, GrowOverGroup) {
+    SetSize(system_, 3_GiB);
+    SetSize(vendor_, 1_GiB + 4_KiB);
+
+    EXPECT_FALSE(UpdateAndExport());
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, Add) {
+    group_->add_partition_names("product");
+    auto product = manifest_.add_partitions();
+    product->set_partition_name("product");
+    SetSize(product, 1_GiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_TRUE(CheckSize("vendor", 1_GiB));
+    EXPECT_TRUE(CheckSize("product", 1_GiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, AddTooBig) {
+    group_->add_partition_names("product");
+    auto product = manifest_.add_partitions();
+    product->set_partition_name("product");
+    SetSize(product, 1_GiB + 4_KiB);
+
+    EXPECT_FALSE(UpdateAndExport());
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, ShrinkAll) {
+    SetSize(system_, 1_GiB);
+    SetSize(vendor_, 512_MiB);
+
+    ASSERT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 1_GiB));
+    EXPECT_TRUE(CheckSize("vendor", 512_MiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, ShrinkAndGrow) {
+    SetSize(system_, 3_GiB + 512_MiB);
+    SetSize(vendor_, 512_MiB);
+
+    ASSERT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 3_GiB + 512_MiB));
+    EXPECT_TRUE(CheckSize("vendor", 512_MiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, ShrinkAndAdd) {
+    SetSize(system_, 2_GiB);
+    SetSize(vendor_, 512_MiB);
+    group_->add_partition_names("product");
+    auto product = manifest_.add_partitions();
+    product->set_partition_name("product");
+    SetSize(product, 1_GiB + 512_MiB);
+
+    ASSERT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_TRUE(CheckSize("vendor", 512_MiB));
+    EXPECT_TRUE(CheckSize("product", 1_GiB + 512_MiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, Delete) {
+    group_->mutable_partition_names()->RemoveLast();
+    // No need to delete it from manifest.partitions as SnapshotMetadataUpdater
+    // should ignore them (treat them as static partitions).
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_EQ(nullptr, builder_->FindPartition(T("vendor")));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, DeleteAndGrow) {
+    group_->mutable_partition_names()->RemoveLast();
+    SetSize(system_, 4_GiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 4_GiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, DeleteAndAdd) {
+    group_->mutable_partition_names()->RemoveLast();
+    group_->add_partition_names("product");
+    auto product = manifest_.add_partitions();
+    product->set_partition_name("product");
+    SetSize(product, 2_GiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_EQ(nullptr, builder_->FindPartition(T("vendor")));
+    EXPECT_TRUE(CheckSize("product", 2_GiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, GrowGroup) {
+    group_->set_size(4_GiB + 512_KiB);
+    SetSize(system_, 2_GiB + 256_KiB);
+    SetSize(vendor_, 2_GiB + 256_KiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 2_GiB + 256_KiB));
+    EXPECT_TRUE(CheckSize("vendor", 2_GiB + 256_KiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, ShrinkGroup) {
+    group_->set_size(1_GiB);
+    SetSize(system_, 512_MiB);
+    SetSize(vendor_, 512_MiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckSize("system", 512_MiB));
+    EXPECT_TRUE(CheckSize("vendor", 512_MiB));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, MoveToNewGroup) {
+    group_->mutable_partition_names()->RemoveLast();
+    group_->set_size(2_GiB);
+
+    auto another_group = manifest_.mutable_dynamic_partition_metadata()->add_groups();
+    another_group->set_name("another_group");
+    another_group->set_size(2_GiB);
+    another_group->add_partition_names("vendor");
+    SetSize(vendor_, 2_GiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_TRUE(CheckGroupSize("group", 2_GiB));
+    EXPECT_TRUE(CheckGroupSize("another_group", 2_GiB));
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_TRUE(CheckGroupName("system", "group"));
+    EXPECT_TRUE(CheckSize("vendor", 2_GiB));
+    EXPECT_TRUE(CheckGroupName("vendor", "another_group"));
+}
+
+TEST_P(SnapshotMetadataUpdaterTest, DeleteAndAddGroup) {
+    manifest_.mutable_dynamic_partition_metadata()->mutable_groups()->RemoveLast();
+    group_ = nullptr;
+
+    auto another_group = manifest_.mutable_dynamic_partition_metadata()->add_groups();
+    another_group->set_name("another_group");
+    another_group->set_size(4_GiB);
+    another_group->add_partition_names("system");
+    another_group->add_partition_names("vendor");
+    another_group->add_partition_names("product");
+    auto product = manifest_.add_partitions();
+    product->set_partition_name("product");
+    SetSize(product, 1_GiB);
+
+    EXPECT_TRUE(UpdateAndExport());
+
+    EXPECT_EQ(nullptr, builder_->FindGroup(T("group")));
+    EXPECT_TRUE(CheckGroupSize("another_group", 4_GiB));
+    EXPECT_TRUE(CheckSize("system", 2_GiB));
+    EXPECT_TRUE(CheckGroupName("system", "another_group"));
+    EXPECT_TRUE(CheckSize("vendor", 1_GiB));
+    EXPECT_TRUE(CheckGroupName("vendor", "another_group"));
+    EXPECT_TRUE(CheckSize("product", 1_GiB));
+    EXPECT_TRUE(CheckGroupName("product", "another_group"));
+}
+
+INSTANTIATE_TEST_SUITE_P(Snapshot, SnapshotMetadataUpdaterTest, testing::Values(0, 1));
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
new file mode 100644
index 0000000..2da0103
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -0,0 +1,1776 @@
+// 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.
+
+#include <libsnapshot/snapshot.h>
+
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <chrono>
+#include <deque>
+#include <future>
+#include <iostream>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <fs_mgr/roots.h>
+#include <fs_mgr_dm_linear.h>
+#include <gtest/gtest.h>
+#include <libdm/dm.h>
+#include <libfiemap/image_manager.h>
+#include <liblp/builder.h>
+#include <storage_literals/storage_literals.h>
+
+#include <android/snapshot/snapshot.pb.h>
+#include <libsnapshot/test_helpers.h>
+#include "utility.h"
+
+namespace android {
+namespace snapshot {
+
+using android::base::unique_fd;
+using android::dm::DeviceMapper;
+using android::dm::DmDeviceState;
+using android::fiemap::IImageManager;
+using android::fs_mgr::BlockDeviceInfo;
+using android::fs_mgr::CreateLogicalPartitionParams;
+using android::fs_mgr::DestroyLogicalPartition;
+using android::fs_mgr::EnsurePathMounted;
+using android::fs_mgr::EnsurePathUnmounted;
+using android::fs_mgr::Extent;
+using android::fs_mgr::Fstab;
+using android::fs_mgr::GetPartitionGroupName;
+using android::fs_mgr::GetPartitionName;
+using android::fs_mgr::Interval;
+using android::fs_mgr::MetadataBuilder;
+using android::fs_mgr::SlotSuffixForSlotNumber;
+using chromeos_update_engine::DeltaArchiveManifest;
+using chromeos_update_engine::DynamicPartitionGroup;
+using chromeos_update_engine::PartitionUpdate;
+using namespace ::testing;
+using namespace android::storage_literals;
+using namespace std::chrono_literals;
+using namespace std::string_literals;
+
+// Global states. See test_helpers.h.
+std::unique_ptr<SnapshotManager> sm;
+TestDeviceInfo* test_device = nullptr;
+std::string fake_super;
+
+void MountMetadata();
+
+class SnapshotTest : public ::testing::Test {
+  public:
+    SnapshotTest() : dm_(DeviceMapper::Instance()) {}
+
+    // This is exposed for main.
+    void Cleanup() {
+        InitializeState();
+        CleanupTestArtifacts();
+    }
+
+  protected:
+    void SetUp() override {
+        SnapshotTestPropertyFetcher::SetUp();
+        InitializeState();
+        CleanupTestArtifacts();
+        FormatFakeSuper();
+        MountMetadata();
+        ASSERT_TRUE(sm->BeginUpdate());
+    }
+
+    void TearDown() override {
+        lock_ = nullptr;
+
+        CleanupTestArtifacts();
+        SnapshotTestPropertyFetcher::TearDown();
+    }
+
+    void InitializeState() {
+        ASSERT_TRUE(sm->EnsureImageManager());
+        image_manager_ = sm->image_manager();
+
+        test_device->set_slot_suffix("_a");
+    }
+
+    void CleanupTestArtifacts() {
+        // Normally cancelling inside a merge is not allowed. Since these
+        // are tests, we don't care, destroy everything that might exist.
+        // Note we hardcode this list because of an annoying quirk: when
+        // completing a merge, the snapshot stops existing, so we can't
+        // get an accurate list to remove.
+        lock_ = nullptr;
+
+        std::vector<std::string> snapshots = {"test-snapshot", "test_partition_a",
+                                              "test_partition_b"};
+        for (const auto& snapshot : snapshots) {
+            ASSERT_TRUE(DeleteSnapshotDevice(snapshot));
+            DeleteBackingImage(image_manager_, snapshot + "-cow-img");
+
+            auto status_file = sm->GetSnapshotStatusFilePath(snapshot);
+            android::base::RemoveFileIfExists(status_file);
+        }
+
+        // Remove stale partitions in fake super.
+        std::vector<std::string> partitions = {
+                "base-device",
+                "test_partition_b",
+                "test_partition_b-base",
+        };
+        for (const auto& partition : partitions) {
+            DeleteDevice(partition);
+        }
+
+        if (sm->GetUpdateState() != UpdateState::None) {
+            auto state_file = sm->GetStateFilePath();
+            unlink(state_file.c_str());
+        }
+    }
+
+    bool AcquireLock() {
+        lock_ = sm->LockExclusive();
+        return !!lock_;
+    }
+
+    // This is so main() can instantiate this to invoke Cleanup.
+    virtual void TestBody() override {}
+
+    void FormatFakeSuper() {
+        BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4096);
+        std::vector<BlockDeviceInfo> devices = {super_device};
+
+        auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
+        ASSERT_NE(builder, nullptr);
+
+        auto metadata = builder->Export();
+        ASSERT_NE(metadata, nullptr);
+
+        TestPartitionOpener opener(fake_super);
+        ASSERT_TRUE(FlashPartitionTable(opener, fake_super, *metadata.get()));
+    }
+
+    // If |path| is non-null, the partition will be mapped after creation.
+    bool CreatePartition(const std::string& name, uint64_t size, std::string* path = nullptr) {
+        TestPartitionOpener opener(fake_super);
+        auto builder = MetadataBuilder::New(opener, "super", 0);
+        if (!builder) return false;
+
+        auto partition = builder->AddPartition(name, 0);
+        if (!partition) return false;
+        if (!builder->ResizePartition(partition, size)) {
+            return false;
+        }
+
+        // Update the source slot.
+        auto metadata = builder->Export();
+        if (!metadata) return false;
+        if (!UpdatePartitionTable(opener, "super", *metadata.get(), 0)) {
+            return false;
+        }
+
+        if (!path) return true;
+
+        CreateLogicalPartitionParams params = {
+                .block_device = fake_super,
+                .metadata = metadata.get(),
+                .partition_name = name,
+                .force_writable = true,
+                .timeout_ms = 10s,
+        };
+        return CreateLogicalPartition(params, path);
+    }
+
+    bool MapUpdatePartitions() {
+        TestPartitionOpener opener(fake_super);
+        auto builder = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
+        if (!builder) return false;
+
+        auto metadata = builder->Export();
+        if (!metadata) return false;
+
+        // Update the destination slot, mark it as updated.
+        if (!UpdatePartitionTable(opener, "super", *metadata.get(), 1)) {
+            return false;
+        }
+
+        for (const auto& partition : metadata->partitions) {
+            CreateLogicalPartitionParams params = {
+                    .block_device = fake_super,
+                    .metadata = metadata.get(),
+                    .partition = &partition,
+                    .force_writable = true,
+                    .timeout_ms = 10s,
+                    .device_name = GetPartitionName(partition) + "-base",
+            };
+            std::string ignore_path;
+            if (!CreateLogicalPartition(params, &ignore_path)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    AssertionResult DeleteSnapshotDevice(const std::string& snapshot) {
+        AssertionResult res = AssertionSuccess();
+        if (!(res = DeleteDevice(snapshot))) return res;
+        if (!(res = DeleteDevice(snapshot + "-inner"))) return res;
+        if (!(res = DeleteDevice(snapshot + "-cow"))) return res;
+        if (!image_manager_->UnmapImageIfExists(snapshot + "-cow-img")) {
+            return AssertionFailure() << "Cannot unmap image " << snapshot << "-cow-img";
+        }
+        if (!(res = DeleteDevice(snapshot + "-base"))) return res;
+        return AssertionSuccess();
+    }
+
+    AssertionResult DeleteDevice(const std::string& device) {
+        if (!dm_.DeleteDeviceIfExists(device)) {
+            return AssertionFailure() << "Can't delete " << device;
+        }
+        return AssertionSuccess();
+    }
+
+    AssertionResult CreateCowImage(const std::string& name) {
+        if (!sm->CreateCowImage(lock_.get(), name)) {
+            return AssertionFailure() << "Cannot create COW image " << name;
+        }
+        std::string cow_device;
+        auto map_res = MapCowImage(name, 10s, &cow_device);
+        if (!map_res) {
+            return map_res;
+        }
+        if (!InitializeCow(cow_device)) {
+            return AssertionFailure() << "Cannot zero fill " << cow_device;
+        }
+        if (!sm->UnmapCowImage(name)) {
+            return AssertionFailure() << "Cannot unmap " << name << " after zero filling it";
+        }
+        return AssertionSuccess();
+    }
+
+    AssertionResult MapCowImage(const std::string& name,
+                                const std::chrono::milliseconds& timeout_ms, std::string* path) {
+        auto cow_image_path = sm->MapCowImage(name, timeout_ms);
+        if (!cow_image_path.has_value()) {
+            return AssertionFailure() << "Cannot map cow image " << name;
+        }
+        *path = *cow_image_path;
+        return AssertionSuccess();
+    }
+
+    // Prepare A/B slot for a partition named "test_partition".
+    AssertionResult PrepareOneSnapshot(uint64_t device_size,
+                                       std::string* out_snap_device = nullptr) {
+        std::string base_device, cow_device, snap_device;
+        if (!CreatePartition("test_partition_a", device_size)) {
+            return AssertionFailure();
+        }
+        if (!MapUpdatePartitions()) {
+            return AssertionFailure();
+        }
+        if (!dm_.GetDmDevicePathByName("test_partition_b-base", &base_device)) {
+            return AssertionFailure();
+        }
+        SnapshotStatus status;
+        status.set_name("test_partition_b");
+        status.set_device_size(device_size);
+        status.set_snapshot_size(device_size);
+        status.set_cow_file_size(device_size);
+        if (!sm->CreateSnapshot(lock_.get(), &status)) {
+            return AssertionFailure();
+        }
+        if (!CreateCowImage("test_partition_b")) {
+            return AssertionFailure();
+        }
+        if (!MapCowImage("test_partition_b", 10s, &cow_device)) {
+            return AssertionFailure();
+        }
+        if (!sm->MapSnapshot(lock_.get(), "test_partition_b", base_device, cow_device, 10s,
+                             &snap_device)) {
+            return AssertionFailure();
+        }
+        if (out_snap_device) {
+            *out_snap_device = std::move(snap_device);
+        }
+        return AssertionSuccess();
+    }
+
+    // Simulate a reboot into the new slot.
+    AssertionResult SimulateReboot() {
+        lock_ = nullptr;
+        if (!sm->FinishedSnapshotWrites()) {
+            return AssertionFailure();
+        }
+        if (!dm_.DeleteDevice("test_partition_b")) {
+            return AssertionFailure();
+        }
+        if (!DestroyLogicalPartition("test_partition_b-base")) {
+            return AssertionFailure();
+        }
+        if (!sm->UnmapCowImage("test_partition_b")) {
+            return AssertionFailure();
+        }
+        return AssertionSuccess();
+    }
+
+    DeviceMapper& dm_;
+    std::unique_ptr<SnapshotManager::LockedFile> lock_;
+    android::fiemap::IImageManager* image_manager_ = nullptr;
+    std::string fake_super_;
+};
+
+TEST_F(SnapshotTest, CreateSnapshot) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kDeviceSize = 1024 * 1024;
+    SnapshotStatus status;
+    status.set_name("test-snapshot");
+    status.set_device_size(kDeviceSize);
+    status.set_snapshot_size(kDeviceSize);
+    status.set_cow_file_size(kDeviceSize);
+    ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &status));
+    ASSERT_TRUE(CreateCowImage("test-snapshot"));
+
+    std::vector<std::string> snapshots;
+    ASSERT_TRUE(sm->ListSnapshots(lock_.get(), &snapshots));
+    ASSERT_EQ(snapshots.size(), 1);
+    ASSERT_EQ(snapshots[0], "test-snapshot");
+
+    // Scope so delete can re-acquire the snapshot file lock.
+    {
+        SnapshotStatus status;
+        ASSERT_TRUE(sm->ReadSnapshotStatus(lock_.get(), "test-snapshot", &status));
+        ASSERT_EQ(status.state(), SnapshotState::CREATED);
+        ASSERT_EQ(status.device_size(), kDeviceSize);
+        ASSERT_EQ(status.snapshot_size(), kDeviceSize);
+    }
+
+    ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
+    ASSERT_TRUE(sm->UnmapCowImage("test-snapshot"));
+    ASSERT_TRUE(sm->DeleteSnapshot(lock_.get(), "test-snapshot"));
+}
+
+TEST_F(SnapshotTest, MapSnapshot) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kDeviceSize = 1024 * 1024;
+    SnapshotStatus status;
+    status.set_name("test-snapshot");
+    status.set_device_size(kDeviceSize);
+    status.set_snapshot_size(kDeviceSize);
+    status.set_cow_file_size(kDeviceSize);
+    ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &status));
+    ASSERT_TRUE(CreateCowImage("test-snapshot"));
+
+    std::string base_device;
+    ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
+
+    std::string cow_device;
+    ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
+
+    std::string snap_device;
+    ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
+                                &snap_device));
+    ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
+}
+
+TEST_F(SnapshotTest, MapPartialSnapshot) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kSnapshotSize = 1024 * 1024;
+    static const uint64_t kDeviceSize = 1024 * 1024 * 2;
+    SnapshotStatus status;
+    status.set_name("test-snapshot");
+    status.set_device_size(kDeviceSize);
+    status.set_snapshot_size(kSnapshotSize);
+    status.set_cow_file_size(kSnapshotSize);
+    ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &status));
+    ASSERT_TRUE(CreateCowImage("test-snapshot"));
+
+    std::string base_device;
+    ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
+
+    std::string cow_device;
+    ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
+
+    std::string snap_device;
+    ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
+                                &snap_device));
+    ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
+}
+
+TEST_F(SnapshotTest, NoMergeBeforeReboot) {
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Merge should fail, since the slot hasn't changed.
+    ASSERT_FALSE(sm->InitiateMerge());
+}
+
+TEST_F(SnapshotTest, CleanFirstStageMount) {
+    // If there's no update in progress, there should be no first-stage mount
+    // needed.
+    TestDeviceInfo* info = new TestDeviceInfo(fake_super);
+    auto sm = SnapshotManager::NewForFirstStageMount(info);
+    ASSERT_NE(sm, nullptr);
+    ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
+}
+
+TEST_F(SnapshotTest, FirstStageMountAfterRollback) {
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // We didn't change the slot, so we shouldn't need snapshots.
+    TestDeviceInfo* info = new TestDeviceInfo(fake_super);
+    auto sm = SnapshotManager::NewForFirstStageMount(info);
+    ASSERT_NE(sm, nullptr);
+    ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
+}
+
+TEST_F(SnapshotTest, Merge) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kDeviceSize = 1024 * 1024;
+    std::string snap_device;
+    ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &snap_device));
+
+    std::string test_string = "This is a test string.";
+    {
+        unique_fd fd(open(snap_device.c_str(), O_RDWR | O_CLOEXEC | O_SYNC));
+        ASSERT_GE(fd, 0);
+        ASSERT_TRUE(android::base::WriteFully(fd, test_string.data(), test_string.size()));
+    }
+
+    // Note: we know there is no inner/outer dm device since we didn't request
+    // a linear segment.
+    DeviceMapper::TargetInfo target;
+    ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
+    ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
+
+    // Release the lock.
+    lock_ = nullptr;
+
+    // Done updating.
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    test_device->set_slot_suffix("_b");
+    ASSERT_TRUE(sm->InitiateMerge());
+
+    // The device should have been switched to a snapshot-merge target.
+    ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
+    ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
+
+    // We should not be able to cancel an update now.
+    ASSERT_FALSE(sm->CancelUpdate());
+
+    ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::MergeCompleted);
+    ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
+
+    // The device should no longer be a snapshot or snapshot-merge.
+    ASSERT_FALSE(sm->IsSnapshotDevice("test_partition_b"));
+
+    // Test that we can read back the string we wrote to the snapshot. Note
+    // that the base device is gone now. |snap_device| contains the correct
+    // partition.
+    unique_fd fd(open(snap_device.c_str(), O_RDONLY | O_CLOEXEC));
+    ASSERT_GE(fd, 0);
+
+    std::string buffer(test_string.size(), '\0');
+    ASSERT_TRUE(android::base::ReadFully(fd, buffer.data(), buffer.size()));
+    ASSERT_EQ(test_string, buffer);
+}
+
+TEST_F(SnapshotTest, FirstStageMountAndMerge) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kDeviceSize = 1024 * 1024;
+    ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
+    ASSERT_TRUE(SimulateReboot());
+
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    ASSERT_TRUE(AcquireLock());
+
+    // Validate that we have a snapshot device.
+    SnapshotStatus status;
+    ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
+    ASSERT_EQ(status.state(), SnapshotState::CREATED);
+
+    DeviceMapper::TargetInfo target;
+    auto dm_name = init->GetSnapshotDeviceName("test_partition_b", status);
+    ASSERT_TRUE(init->IsSnapshotDevice(dm_name, &target));
+    ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
+}
+
+TEST_F(SnapshotTest, FlashSuperDuringUpdate) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kDeviceSize = 1024 * 1024;
+    ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
+    ASSERT_TRUE(SimulateReboot());
+
+    // Reflash the super partition.
+    FormatFakeSuper();
+    ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
+
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    ASSERT_TRUE(AcquireLock());
+
+    SnapshotStatus status;
+    ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
+
+    // We should not get a snapshot device now.
+    DeviceMapper::TargetInfo target;
+    auto dm_name = init->GetSnapshotDeviceName("test_partition_b", status);
+    ASSERT_FALSE(init->IsSnapshotDevice(dm_name, &target));
+
+    // We should see a cancelled update as well.
+    lock_ = nullptr;
+    ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
+}
+
+TEST_F(SnapshotTest, FlashSuperDuringMerge) {
+    ASSERT_TRUE(AcquireLock());
+
+    static const uint64_t kDeviceSize = 1024 * 1024;
+    ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
+    ASSERT_TRUE(SimulateReboot());
+
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+    ASSERT_TRUE(init->InitiateMerge());
+
+    // Now, reflash super. Note that we haven't called ProcessUpdateState, so the
+    // status is still Merging.
+    ASSERT_TRUE(DeleteSnapshotDevice("test_partition_b"));
+    ASSERT_TRUE(init->image_manager()->UnmapImageIfExists("test_partition_b-cow-img"));
+    FormatFakeSuper();
+    ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // Because the status is Merging, we must call ProcessUpdateState, which should
+    // detect a cancelled update.
+    ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
+    ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
+}
+
+TEST_F(SnapshotTest, UpdateBootControlHal) {
+    ASSERT_TRUE(AcquireLock());
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
+
+    ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
+    ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
+}
+
+enum class Request { UNKNOWN, LOCK_SHARED, LOCK_EXCLUSIVE, UNLOCK, EXIT };
+std::ostream& operator<<(std::ostream& os, Request request) {
+    switch (request) {
+        case Request::LOCK_SHARED:
+            return os << "Shared";
+        case Request::LOCK_EXCLUSIVE:
+            return os << "Exclusive";
+        case Request::UNLOCK:
+            return os << "Unlock";
+        case Request::EXIT:
+            return os << "Exit";
+        case Request::UNKNOWN:
+            [[fallthrough]];
+        default:
+            return os << "Unknown";
+    }
+}
+
+class LockTestConsumer {
+  public:
+    AssertionResult MakeRequest(Request new_request) {
+        {
+            std::unique_lock<std::mutex> ulock(mutex_);
+            requests_.push_back(new_request);
+        }
+        cv_.notify_all();
+        return AssertionSuccess() << "Request " << new_request << " successful";
+    }
+
+    template <typename R, typename P>
+    AssertionResult WaitFulfill(std::chrono::duration<R, P> timeout) {
+        std::unique_lock<std::mutex> ulock(mutex_);
+        if (cv_.wait_for(ulock, timeout, [this] { return requests_.empty(); })) {
+            return AssertionSuccess() << "All requests_ fulfilled.";
+        }
+        return AssertionFailure() << "Timeout waiting for fulfilling " << requests_.size()
+                                  << " request(s), first one is "
+                                  << (requests_.empty() ? Request::UNKNOWN : requests_.front());
+    }
+
+    void StartHandleRequestsInBackground() {
+        future_ = std::async(std::launch::async, &LockTestConsumer::HandleRequests, this);
+    }
+
+  private:
+    void HandleRequests() {
+        static constexpr auto consumer_timeout = 3s;
+
+        auto next_request = Request::UNKNOWN;
+        do {
+            // Peek next request.
+            {
+                std::unique_lock<std::mutex> ulock(mutex_);
+                if (cv_.wait_for(ulock, consumer_timeout, [this] { return !requests_.empty(); })) {
+                    next_request = requests_.front();
+                } else {
+                    next_request = Request::EXIT;
+                }
+            }
+
+            // Handle next request.
+            switch (next_request) {
+                case Request::LOCK_SHARED: {
+                    lock_ = sm->LockShared();
+                } break;
+                case Request::LOCK_EXCLUSIVE: {
+                    lock_ = sm->LockExclusive();
+                } break;
+                case Request::EXIT:
+                    [[fallthrough]];
+                case Request::UNLOCK: {
+                    lock_.reset();
+                } break;
+                case Request::UNKNOWN:
+                    [[fallthrough]];
+                default:
+                    break;
+            }
+
+            // Pop next request. This thread is the only thread that
+            // pops from the front of the requests_ deque.
+            {
+                std::unique_lock<std::mutex> ulock(mutex_);
+                if (next_request == Request::EXIT) {
+                    requests_.clear();
+                } else {
+                    requests_.pop_front();
+                }
+            }
+            cv_.notify_all();
+        } while (next_request != Request::EXIT);
+    }
+
+    std::mutex mutex_;
+    std::condition_variable cv_;
+    std::deque<Request> requests_;
+    std::unique_ptr<SnapshotManager::LockedFile> lock_;
+    std::future<void> future_;
+};
+
+class LockTest : public ::testing::Test {
+  public:
+    void SetUp() {
+        first_consumer.StartHandleRequestsInBackground();
+        second_consumer.StartHandleRequestsInBackground();
+    }
+
+    void TearDown() {
+        EXPECT_TRUE(first_consumer.MakeRequest(Request::EXIT));
+        EXPECT_TRUE(second_consumer.MakeRequest(Request::EXIT));
+    }
+
+    static constexpr auto request_timeout = 500ms;
+    LockTestConsumer first_consumer;
+    LockTestConsumer second_consumer;
+};
+
+TEST_F(LockTest, SharedShared) {
+    ASSERT_TRUE(first_consumer.MakeRequest(Request::LOCK_SHARED));
+    ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
+    ASSERT_TRUE(second_consumer.MakeRequest(Request::LOCK_SHARED));
+    ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout));
+}
+
+using LockTestParam = std::pair<Request, Request>;
+class LockTestP : public LockTest, public ::testing::WithParamInterface<LockTestParam> {};
+TEST_P(LockTestP, Test) {
+    ASSERT_TRUE(first_consumer.MakeRequest(GetParam().first));
+    ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
+    ASSERT_TRUE(second_consumer.MakeRequest(GetParam().second));
+    ASSERT_FALSE(second_consumer.WaitFulfill(request_timeout))
+            << "Should not be able to " << GetParam().second << " while separate thread "
+            << GetParam().first;
+    ASSERT_TRUE(first_consumer.MakeRequest(Request::UNLOCK));
+    ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout))
+            << "Should be able to hold lock that is released by separate thread";
+}
+INSTANTIATE_TEST_SUITE_P(
+        LockTest, LockTestP,
+        testing::Values(LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_EXCLUSIVE},
+                        LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_SHARED},
+                        LockTestParam{Request::LOCK_SHARED, Request::LOCK_EXCLUSIVE}),
+        [](const testing::TestParamInfo<LockTestP::ParamType>& info) {
+            std::stringstream ss;
+            ss << info.param.first << info.param.second;
+            return ss.str();
+        });
+
+class SnapshotUpdateTest : public SnapshotTest {
+  public:
+    void SetUp() override {
+        SnapshotTest::SetUp();
+        Cleanup();
+
+        // Cleanup() changes slot suffix, so initialize it again.
+        test_device->set_slot_suffix("_a");
+
+        opener_ = std::make_unique<TestPartitionOpener>(fake_super);
+
+        // Create a fake update package metadata.
+        // Not using full name "system", "vendor", "product" because these names collide with the
+        // mapped partitions on the running device.
+        // Each test modifies manifest_ slightly to indicate changes to the partition layout.
+        group_ = manifest_.mutable_dynamic_partition_metadata()->add_groups();
+        group_->set_name("group");
+        group_->set_size(kGroupSize);
+        group_->add_partition_names("sys");
+        group_->add_partition_names("vnd");
+        group_->add_partition_names("prd");
+        sys_ = manifest_.add_partitions();
+        sys_->set_partition_name("sys");
+        SetSize(sys_, 3_MiB);
+        vnd_ = manifest_.add_partitions();
+        vnd_->set_partition_name("vnd");
+        SetSize(vnd_, 3_MiB);
+        prd_ = manifest_.add_partitions();
+        prd_->set_partition_name("prd");
+        SetSize(prd_, 3_MiB);
+
+        // Initialize source partition metadata using |manifest_|.
+        src_ = MetadataBuilder::New(*opener_, "super", 0);
+        ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
+        // Add sys_b which is like system_other.
+        ASSERT_TRUE(src_->AddGroup("group_b", kGroupSize));
+        auto partition = src_->AddPartition("sys_b", "group_b", 0);
+        ASSERT_NE(nullptr, partition);
+        ASSERT_TRUE(src_->ResizePartition(partition, 1_MiB));
+        auto metadata = src_->Export();
+        ASSERT_NE(nullptr, metadata);
+        ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
+
+        // Map source partitions. Additionally, map sys_b to simulate system_other after flashing.
+        std::string path;
+        for (const auto& name : {"sys_a", "vnd_a", "prd_a", "sys_b"}) {
+            ASSERT_TRUE(CreateLogicalPartition(
+                    CreateLogicalPartitionParams{
+                            .block_device = fake_super,
+                            .metadata_slot = 0,
+                            .partition_name = name,
+                            .timeout_ms = 1s,
+                            .partition_opener = opener_.get(),
+                    },
+                    &path));
+            ASSERT_TRUE(WriteRandomData(path));
+            auto hash = GetHash(path);
+            ASSERT_TRUE(hash.has_value());
+            hashes_[name] = *hash;
+        }
+    }
+    void TearDown() override {
+        Cleanup();
+        SnapshotTest::TearDown();
+    }
+    void Cleanup() {
+        if (!image_manager_) {
+            InitializeState();
+        }
+        MountMetadata();
+        for (const auto& suffix : {"_a", "_b"}) {
+            test_device->set_slot_suffix(suffix);
+            EXPECT_TRUE(sm->CancelUpdate()) << suffix;
+        }
+        EXPECT_TRUE(UnmapAll());
+    }
+
+    AssertionResult IsPartitionUnchanged(const std::string& name) {
+        std::string path;
+        if (!dm_.GetDmDevicePathByName(name, &path)) {
+            return AssertionFailure() << "Path of " << name << " cannot be determined";
+        }
+        auto hash = GetHash(path);
+        if (!hash.has_value()) {
+            return AssertionFailure() << "Cannot read partition " << name << ": " << path;
+        }
+        auto it = hashes_.find(name);
+        if (it == hashes_.end()) {
+            return AssertionFailure() << "No existing hash for " << name << ". Bad test code?";
+        }
+        if (it->second != *hash) {
+            return AssertionFailure() << "Content of " << name << " has changed";
+        }
+        return AssertionSuccess();
+    }
+
+    std::optional<uint64_t> GetSnapshotSize(const std::string& name) {
+        if (!AcquireLock()) {
+            return std::nullopt;
+        }
+        auto local_lock = std::move(lock_);
+
+        SnapshotStatus status;
+        if (!sm->ReadSnapshotStatus(local_lock.get(), name, &status)) {
+            return std::nullopt;
+        }
+        return status.snapshot_size();
+    }
+
+    AssertionResult UnmapAll() {
+        for (const auto& name : {"sys", "vnd", "prd"}) {
+            if (!dm_.DeleteDeviceIfExists(name + "_a"s)) {
+                return AssertionFailure() << "Cannot unmap " << name << "_a";
+            }
+            if (!DeleteSnapshotDevice(name + "_b"s)) {
+                return AssertionFailure() << "Cannot delete snapshot " << name << "_b";
+            }
+        }
+        return AssertionSuccess();
+    }
+
+    AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path = nullptr) {
+        std::string real_path;
+        if (!sm->MapUpdateSnapshot(
+                    CreateLogicalPartitionParams{
+                            .block_device = fake_super,
+                            .metadata_slot = 1,
+                            .partition_name = name,
+                            .timeout_ms = 10s,
+                            .partition_opener = opener_.get(),
+                    },
+                    &real_path)) {
+            return AssertionFailure() << "Unable to map snapshot " << name;
+        }
+        if (path) {
+            *path = real_path;
+        }
+        return AssertionSuccess() << "Mapped snapshot " << name << " to " << real_path;
+    }
+
+    AssertionResult WriteSnapshotAndHash(const std::string& name,
+                                         std::optional<size_t> size = std::nullopt) {
+        std::string path;
+        auto res = MapUpdateSnapshot(name, &path);
+        if (!res) {
+            return res;
+        }
+
+        std::string size_string = size ? (std::to_string(*size) + " bytes") : "";
+
+        if (!WriteRandomData(path, size, &hashes_[name])) {
+            return AssertionFailure() << "Unable to write " << size_string << " to " << path
+                                      << " for partition " << name;
+        }
+
+        return AssertionSuccess() << "Written " << size_string << " to " << path
+                                  << " for snapshot partition " << name
+                                  << ", hash: " << hashes_[name];
+    }
+
+    AssertionResult MapUpdateSnapshots(const std::vector<std::string>& names = {"sys_b", "vnd_b",
+                                                                                "prd_b"}) {
+        for (const auto& name : names) {
+            auto res = MapUpdateSnapshot(name);
+            if (!res) {
+                return res;
+            }
+        }
+        return AssertionSuccess();
+    }
+
+    // Create fake install operations to grow the COW device size.
+    void AddOperation(PartitionUpdate* partition_update, uint64_t size_bytes = 0) {
+        auto e = partition_update->add_operations()->add_dst_extents();
+        e->set_start_block(0);
+        if (size_bytes == 0) {
+            size_bytes = GetSize(partition_update);
+        }
+        e->set_num_blocks(size_bytes / manifest_.block_size());
+    }
+
+    void AddOperationForPartitions(std::vector<PartitionUpdate*> partitions = {}) {
+        if (partitions.empty()) {
+            partitions = {sys_, vnd_, prd_};
+        }
+        for (auto* partition : partitions) {
+            AddOperation(partition);
+        }
+    }
+
+    std::unique_ptr<TestPartitionOpener> opener_;
+    DeltaArchiveManifest manifest_;
+    std::unique_ptr<MetadataBuilder> src_;
+    std::map<std::string, std::string> hashes_;
+
+    PartitionUpdate* sys_ = nullptr;
+    PartitionUpdate* vnd_ = nullptr;
+    PartitionUpdate* prd_ = nullptr;
+    DynamicPartitionGroup* group_ = nullptr;
+};
+
+// Test full update flow executed by update_engine. Some partitions uses super empty space,
+// some uses images, and some uses both.
+// Also test UnmapUpdateSnapshot unmaps everything.
+// Also test first stage mount and merge after this.
+TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
+    // OTA client blindly unmaps all partitions that are possibly mapped.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
+    }
+
+    // Grow all partitions.
+    constexpr uint64_t partition_size = 3788_KiB;
+    SetSize(sys_, partition_size);
+    SetSize(vnd_, partition_size);
+    SetSize(prd_, partition_size);
+
+    AddOperationForPartitions();
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Test that partitions prioritize using space in super.
+    auto tgt = MetadataBuilder::New(*opener_, "super", 1);
+    ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
+    ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
+    ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name, partition_size));
+    }
+
+    // Assert that source partitions aren't affected.
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // Check that the target partitions have the same content.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    // Initiate the merge and wait for it to be completed.
+    ASSERT_EQ(UpdateState::MergeCompleted, init->InitiateMergeAndWait());
+
+    // Check that the target partitions have the same content after the merge.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name))
+                << "Content of " << name << " changes after the merge";
+    }
+}
+
+// Test that if new system partitions uses empty space in super, that region is not snapshotted.
+TEST_F(SnapshotUpdateTest, DirectWriteEmptySpace) {
+    GTEST_SKIP() << "b/141889746";
+    SetSize(sys_, 4_MiB);
+    // vnd_b and prd_b are unchanged.
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_EQ(3_MiB, GetSnapshotSize("sys_b").value_or(0));
+}
+
+// Test that if new system partitions uses space of old vendor partition, that region is
+// snapshotted.
+TEST_F(SnapshotUpdateTest, SnapshotOldPartitions) {
+    SetSize(sys_, 4_MiB);  // grows
+    SetSize(vnd_, 2_MiB);  // shrinks
+    // prd_b is unchanged
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_EQ(4_MiB, GetSnapshotSize("sys_b").value_or(0));
+}
+
+// Test that even if there seem to be empty space in target metadata, COW partition won't take
+// it because they are used by old partitions.
+TEST_F(SnapshotUpdateTest, CowPartitionDoNotTakeOldPartitions) {
+    SetSize(sys_, 2_MiB);  // shrinks
+    // vnd_b and prd_b are unchanged.
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    auto tgt = MetadataBuilder::New(*opener_, "super", 1);
+    ASSERT_NE(nullptr, tgt);
+    auto metadata = tgt->Export();
+    ASSERT_NE(nullptr, metadata);
+    std::vector<std::string> written;
+    // Write random data to all COW partitions in super
+    for (auto p : metadata->partitions) {
+        if (GetPartitionGroupName(metadata->groups[p.group_index]) != kCowGroupName) {
+            continue;
+        }
+        std::string path;
+        ASSERT_TRUE(CreateLogicalPartition(
+                CreateLogicalPartitionParams{
+                        .block_device = fake_super,
+                        .metadata = metadata.get(),
+                        .partition = &p,
+                        .timeout_ms = 1s,
+                        .partition_opener = opener_.get(),
+                },
+                &path));
+        ASSERT_TRUE(WriteRandomData(path));
+        written.push_back(GetPartitionName(p));
+    }
+    ASSERT_FALSE(written.empty())
+            << "No COW partitions are created even if there are empty space in super partition";
+
+    // Make sure source partitions aren't affected.
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+}
+
+// Test that it crashes after creating snapshot status file but before creating COW image, then
+// calling CreateUpdateSnapshots again works.
+TEST_F(SnapshotUpdateTest, SnapshotStatusFileWithoutCow) {
+    // Write some trash snapshot files to simulate leftovers from previous runs.
+    {
+        ASSERT_TRUE(AcquireLock());
+        auto local_lock = std::move(lock_);
+        SnapshotStatus status;
+        status.set_name("sys_b");
+        ASSERT_TRUE(sm->WriteSnapshotStatus(local_lock.get(), status));
+        ASSERT_TRUE(image_manager_->CreateBackingImage("sys_b-cow-img", 1_MiB,
+                                                       IImageManager::CREATE_IMAGE_DEFAULT));
+    }
+
+    // Redo the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
+
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Check that target partitions can be mapped.
+    EXPECT_TRUE(MapUpdateSnapshots());
+}
+
+// Test that the old partitions are not modified.
+TEST_F(SnapshotUpdateTest, TestRollback) {
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
+
+    AddOperationForPartitions();
+
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name));
+    }
+
+    // Assert that source partitions aren't affected.
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // Check that the target partitions have the same content.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    // Simulate shutting down the device again.
+    ASSERT_TRUE(UnmapAll());
+    init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_a"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_FALSE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // Assert that the source partitions aren't affected.
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+}
+
+// Test that if an update is applied but not booted into, it can be canceled.
+TEST_F(SnapshotUpdateTest, CancelAfterApply) {
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+    ASSERT_TRUE(sm->CancelUpdate());
+}
+
+static std::vector<Interval> ToIntervals(const std::vector<std::unique_ptr<Extent>>& extents) {
+    std::vector<Interval> ret;
+    std::transform(extents.begin(), extents.end(), std::back_inserter(ret),
+                   [](const auto& extent) { return extent->AsLinearExtent()->AsInterval(); });
+    return ret;
+}
+
+// Test that at the second update, old COW partition spaces are reclaimed.
+TEST_F(SnapshotUpdateTest, ReclaimCow) {
+    // Execute the first update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_TRUE(MapUpdateSnapshots());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+    init = nullptr;
+
+    // Initiate the merge and wait for it to be completed.
+    auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_EQ(UpdateState::MergeCompleted, new_sm->InitiateMergeAndWait());
+
+    // Execute the second update.
+    ASSERT_TRUE(new_sm->BeginUpdate());
+    ASSERT_TRUE(new_sm->CreateUpdateSnapshots(manifest_));
+
+    // Check that the old COW space is reclaimed and does not occupy space of mapped partitions.
+    auto src = MetadataBuilder::New(*opener_, "super", 1);
+    auto tgt = MetadataBuilder::New(*opener_, "super", 0);
+    for (const auto& cow_part_name : {"sys_a-cow", "vnd_a-cow", "prd_a-cow"}) {
+        auto* cow_part = tgt->FindPartition(cow_part_name);
+        ASSERT_NE(nullptr, cow_part) << cow_part_name << " does not exist in target metadata";
+        auto cow_intervals = ToIntervals(cow_part->extents());
+        for (const auto& old_part_name : {"sys_b", "vnd_b", "prd_b"}) {
+            auto* old_part = src->FindPartition(old_part_name);
+            ASSERT_NE(nullptr, old_part) << old_part_name << " does not exist in source metadata";
+            auto old_intervals = ToIntervals(old_part->extents());
+
+            auto intersect = Interval::Intersect(cow_intervals, old_intervals);
+            ASSERT_TRUE(intersect.empty()) << "COW uses space of source partitions";
+        }
+    }
+}
+
+TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) {
+    constexpr auto kRetrofitGroupSize = kGroupSize / 2;
+
+    // Initialize device-mapper / disk
+    ASSERT_TRUE(UnmapAll());
+    FormatFakeSuper();
+
+    // Setup source partition metadata to have both _a and _b partitions.
+    src_ = MetadataBuilder::New(*opener_, "super", 0);
+    ASSERT_NE(nullptr, src_);
+    for (const auto& suffix : {"_a"s, "_b"s}) {
+        ASSERT_TRUE(src_->AddGroup(group_->name() + suffix, kRetrofitGroupSize));
+        for (const auto& name : {"sys"s, "vnd"s, "prd"s}) {
+            auto partition = src_->AddPartition(name + suffix, group_->name() + suffix, 0);
+            ASSERT_NE(nullptr, partition);
+            ASSERT_TRUE(src_->ResizePartition(partition, 2_MiB));
+        }
+    }
+    auto metadata = src_->Export();
+    ASSERT_NE(nullptr, metadata);
+    ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
+
+    // Flash source partitions
+    std::string path;
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(CreateLogicalPartition(
+                CreateLogicalPartitionParams{
+                        .block_device = fake_super,
+                        .metadata_slot = 0,
+                        .partition_name = name,
+                        .timeout_ms = 1s,
+                        .partition_opener = opener_.get(),
+                },
+                &path));
+        ASSERT_TRUE(WriteRandomData(path));
+        auto hash = GetHash(path);
+        ASSERT_TRUE(hash.has_value());
+        hashes_[name] = *hash;
+    }
+
+    // Setup manifest.
+    group_->set_size(kRetrofitGroupSize);
+    for (auto* partition : {sys_, vnd_, prd_}) {
+        SetSize(partition, 2_MiB);
+    }
+    AddOperationForPartitions();
+
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Test that COW image should not be created for retrofit devices; super
+    // should be big enough.
+    ASSERT_FALSE(image_manager_->BackingImageExists("sys_b-cow-img"));
+    ASSERT_FALSE(image_manager_->BackingImageExists("vnd_b-cow-img"));
+    ASSERT_FALSE(image_manager_->BackingImageExists("prd_b-cow-img"));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name));
+    }
+
+    // Assert that source partitions aren't affected.
+    for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name));
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+}
+
+TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
+    // Make source partitions as big as possible to force COW image to be created.
+    SetSize(sys_, 5_MiB);
+    SetSize(vnd_, 5_MiB);
+    SetSize(prd_, 5_MiB);
+    src_ = MetadataBuilder::New(*opener_, "super", 0);
+    src_->RemoveGroupAndPartitions(group_->name() + "_a");
+    src_->RemoveGroupAndPartitions(group_->name() + "_b");
+    ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
+    auto metadata = src_->Export();
+    ASSERT_NE(nullptr, metadata);
+    ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
+
+    // OTA client blindly unmaps all partitions that are possibly mapped.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
+    }
+
+    // Add operations for sys. The whole device is written.
+    AddOperation(sys_);
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_TRUE(MapUpdateSnapshots());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    // Normally we should use NewForFirstStageMount, but if so, "gsid.mapped_image.sys_b-cow-img"
+    // won't be set.
+    auto init = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // Keep an open handle to the cow device. This should cause the merge to
+    // be incomplete.
+    auto cow_path = android::base::GetProperty("gsid.mapped_image.sys_b-cow-img", "");
+    unique_fd fd(open(cow_path.c_str(), O_RDONLY | O_CLOEXEC));
+    ASSERT_GE(fd, 0);
+
+    // COW cannot be removed due to open fd, so expect a soft failure.
+    ASSERT_EQ(UpdateState::MergeNeedsReboot, init->InitiateMergeAndWait());
+
+    // Simulate shutting down the device.
+    fd.reset();
+    ASSERT_TRUE(UnmapAll());
+
+    // init does first stage mount again.
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // sys_b should be mapped as a dm-linear device directly.
+    ASSERT_FALSE(sm->IsSnapshotDevice("sys_b", nullptr));
+
+    // Merge should be able to complete now.
+    ASSERT_EQ(UpdateState::MergeCompleted, init->InitiateMergeAndWait());
+}
+
+class MetadataMountedTest : public SnapshotUpdateTest {
+  public:
+    void SetUp() override {
+        metadata_dir_ = test_device->GetMetadataDir();
+        ASSERT_TRUE(ReadDefaultFstab(&fstab_));
+    }
+    void TearDown() override {
+        SetUp();
+        // Remount /metadata
+        test_device->set_recovery(false);
+        EXPECT_TRUE(android::fs_mgr::EnsurePathMounted(&fstab_, metadata_dir_));
+    }
+    AssertionResult IsMetadataMounted() {
+        Fstab mounted_fstab;
+        if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
+            ADD_FAILURE() << "Failed to scan mounted volumes";
+            return AssertionFailure() << "Failed to scan mounted volumes";
+        }
+
+        auto entry = GetEntryForPath(&fstab_, metadata_dir_);
+        if (entry == nullptr) {
+            return AssertionFailure() << "No mount point found in fstab for path " << metadata_dir_;
+        }
+
+        auto mv = GetEntryForMountPoint(&mounted_fstab, entry->mount_point);
+        if (mv == nullptr) {
+            return AssertionFailure() << metadata_dir_ << " is not mounted";
+        }
+        return AssertionSuccess() << metadata_dir_ << " is mounted";
+    }
+    std::string metadata_dir_;
+    Fstab fstab_;
+};
+
+void MountMetadata() {
+    MetadataMountedTest().TearDown();
+}
+
+TEST_F(MetadataMountedTest, Android) {
+    auto device = sm->EnsureMetadataMounted();
+    EXPECT_NE(nullptr, device);
+    device.reset();
+
+    EXPECT_TRUE(IsMetadataMounted());
+    EXPECT_TRUE(sm->CancelUpdate()) << "Metadata dir should never be unmounted in Android mode";
+}
+
+TEST_F(MetadataMountedTest, Recovery) {
+    test_device->set_recovery(true);
+    metadata_dir_ = test_device->GetMetadataDir();
+
+    EXPECT_TRUE(android::fs_mgr::EnsurePathUnmounted(&fstab_, metadata_dir_));
+    EXPECT_FALSE(IsMetadataMounted());
+
+    auto device = sm->EnsureMetadataMounted();
+    EXPECT_NE(nullptr, device);
+    EXPECT_TRUE(IsMetadataMounted());
+
+    device.reset();
+    EXPECT_FALSE(IsMetadataMounted());
+}
+
+// Test that during a merge, we can wipe data in recovery.
+TEST_F(SnapshotUpdateTest, MergeInRecovery) {
+    // Execute the first update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_TRUE(MapUpdateSnapshots());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+    init = nullptr;
+
+    // Initiate the merge and then immediately stop it to simulate a reboot.
+    auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_TRUE(new_sm->InitiateMerge());
+    ASSERT_TRUE(UnmapAll());
+
+    // Simulate a reboot into recovery.
+    auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
+    test_device->set_recovery(true);
+    new_sm = SnapshotManager::NewForFirstStageMount(test_device.release());
+
+    ASSERT_TRUE(new_sm->HandleImminentDataWipe());
+    ASSERT_EQ(new_sm->GetUpdateState(), UpdateState::None);
+}
+
+// Test that after an OTA, before a merge, we can wipe data in recovery.
+TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) {
+    // Execute the first update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_TRUE(MapUpdateSnapshots());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // Simulate a reboot into recovery.
+    auto test_device = new TestDeviceInfo(fake_super, "_b");
+    test_device->set_recovery(true);
+    auto new_sm = SnapshotManager::NewForFirstStageMount(test_device);
+
+    ASSERT_TRUE(new_sm->HandleImminentDataWipe());
+    // Manually mount metadata so that we can call GetUpdateState() below.
+    MountMetadata();
+    EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
+    EXPECT_TRUE(test_device->IsSlotUnbootable(1));
+    EXPECT_FALSE(test_device->IsSlotUnbootable(0));
+}
+
+// Test that after an OTA and a bootloader rollback with no merge, we can wipe
+// data in recovery.
+TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) {
+    // Execute the first update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_TRUE(MapUpdateSnapshots());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // Simulate a rollback, with reboot into recovery.
+    auto test_device = new TestDeviceInfo(fake_super, "_a");
+    test_device->set_recovery(true);
+    auto new_sm = SnapshotManager::NewForFirstStageMount(test_device);
+
+    ASSERT_TRUE(new_sm->HandleImminentDataWipe());
+    EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
+    EXPECT_FALSE(test_device->IsSlotUnbootable(0));
+    EXPECT_FALSE(test_device->IsSlotUnbootable(0));
+}
+
+TEST_F(SnapshotUpdateTest, Hashtree) {
+    constexpr auto partition_size = 4_MiB;
+    constexpr auto data_size = 3_MiB;
+    constexpr auto hashtree_size = 512_KiB;
+    constexpr auto fec_size = partition_size - data_size - hashtree_size;
+
+    const auto block_size = manifest_.block_size();
+    SetSize(sys_, partition_size);
+    AddOperation(sys_, data_size);
+
+    // Set hastree extents.
+    sys_->mutable_hash_tree_data_extent()->set_start_block(0);
+    sys_->mutable_hash_tree_data_extent()->set_num_blocks(data_size / block_size);
+
+    sys_->mutable_hash_tree_extent()->set_start_block(data_size / block_size);
+    sys_->mutable_hash_tree_extent()->set_num_blocks(hashtree_size / block_size);
+
+    // Set FEC extents.
+    sys_->mutable_fec_data_extent()->set_start_block(0);
+    sys_->mutable_fec_data_extent()->set_num_blocks((data_size + hashtree_size) / block_size);
+
+    sys_->mutable_fec_extent()->set_start_block((data_size + hashtree_size) / block_size);
+    sys_->mutable_fec_extent()->set_num_blocks(fec_size / block_size);
+
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Map and write some data to target partition.
+    ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
+    ASSERT_TRUE(WriteSnapshotAndHash("sys_b", partition_size));
+
+    // Finish update.
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(init, nullptr);
+    ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
+    ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+
+    // Check that the target partition have the same content. Hashtree and FEC extents
+    // should be accounted for.
+    ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
+}
+
+// Test for overflow bit after update
+TEST_F(SnapshotUpdateTest, Overflow) {
+    const auto actual_write_size = GetSize(sys_);
+    const auto declared_write_size = actual_write_size - 1_MiB;
+
+    AddOperation(sys_, declared_write_size);
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Map and write some data to target partitions.
+    ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
+    ASSERT_TRUE(WriteSnapshotAndHash("sys_b", actual_write_size));
+
+    std::vector<android::dm::DeviceMapper::TargetInfo> table;
+    ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table));
+    ASSERT_EQ(1u, table.size());
+    EXPECT_TRUE(table[0].IsOverflowSnapshot());
+
+    ASSERT_FALSE(sm->FinishedSnapshotWrites())
+            << "FinishedSnapshotWrites should detect overflow of CoW device.";
+}
+
+TEST_F(SnapshotUpdateTest, WaitForMerge) {
+    AddOperationForPartitions();
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    // Write some data to target partitions.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(WriteSnapshotAndHash(name));
+    }
+
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    // After reboot, init does first stage mount.
+    {
+        auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
+        ASSERT_NE(nullptr, init);
+        ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+    }
+
+    auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
+    ASSERT_NE(nullptr, new_sm);
+
+    auto waiter = std::async(std::launch::async, [&new_sm] { return new_sm->WaitForMerge(); });
+    ASSERT_EQ(std::future_status::timeout, waiter.wait_for(1s))
+            << "WaitForMerge should block when not initiated";
+
+    auto merger =
+            std::async(std::launch::async, [&new_sm] { return new_sm->InitiateMergeAndWait(); });
+    // Small images, so should be merged pretty quickly.
+    ASSERT_EQ(std::future_status::ready, waiter.wait_for(3s)) << "WaitForMerge did not finish";
+    ASSERT_TRUE(waiter.get());
+    ASSERT_THAT(merger.get(), AnyOf(UpdateState::None, UpdateState::MergeCompleted));
+}
+
+class FlashAfterUpdateTest : public SnapshotUpdateTest,
+                             public WithParamInterface<std::tuple<uint32_t, bool>> {
+  public:
+    AssertionResult InitiateMerge(const std::string& slot_suffix) {
+        auto sm = SnapshotManager::New(new TestDeviceInfo(fake_super, slot_suffix));
+        if (!sm->CreateLogicalAndSnapshotPartitions("super")) {
+            return AssertionFailure() << "Cannot CreateLogicalAndSnapshotPartitions";
+        }
+        if (!sm->InitiateMerge()) {
+            return AssertionFailure() << "Cannot initiate merge";
+        }
+        return AssertionSuccess();
+    }
+};
+
+TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) {
+    // OTA client blindly unmaps all partitions that are possibly mapped.
+    for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
+        ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
+    }
+
+    // Execute the update.
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+    ASSERT_TRUE(MapUpdateSnapshots());
+    ASSERT_TRUE(sm->FinishedSnapshotWrites());
+
+    // Simulate shutting down the device.
+    ASSERT_TRUE(UnmapAll());
+
+    if (std::get<1>(GetParam()) /* merge */) {
+        ASSERT_TRUE(InitiateMerge("_b"));
+        // Simulate shutting down the device after merge has initiated.
+        ASSERT_TRUE(UnmapAll());
+    }
+
+    auto flashed_slot = std::get<0>(GetParam());
+    auto flashed_slot_suffix = SlotSuffixForSlotNumber(flashed_slot);
+
+    // Simulate flashing |flashed_slot|. This clears the UPDATED flag.
+    auto flashed_builder = MetadataBuilder::New(*opener_, "super", flashed_slot);
+    flashed_builder->RemoveGroupAndPartitions(group_->name() + flashed_slot_suffix);
+    flashed_builder->RemoveGroupAndPartitions(kCowGroupName);
+    ASSERT_TRUE(FillFakeMetadata(flashed_builder.get(), manifest_, flashed_slot_suffix));
+
+    // Deliberately remove a partition from this build so that
+    // InitiateMerge do not switch state to "merging". This is possible in
+    // practice because the list of dynamic partitions may change.
+    ASSERT_NE(nullptr, flashed_builder->FindPartition("prd" + flashed_slot_suffix));
+    flashed_builder->RemovePartition("prd" + flashed_slot_suffix);
+
+    auto flashed_metadata = flashed_builder->Export();
+    ASSERT_NE(nullptr, flashed_metadata);
+    ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, flashed_slot));
+
+    std::string path;
+    for (const auto& name : {"sys", "vnd"}) {
+        ASSERT_TRUE(CreateLogicalPartition(
+                CreateLogicalPartitionParams{
+                        .block_device = fake_super,
+                        .metadata_slot = flashed_slot,
+                        .partition_name = name + flashed_slot_suffix,
+                        .timeout_ms = 1s,
+                        .partition_opener = opener_.get(),
+                },
+                &path));
+        ASSERT_TRUE(WriteRandomData(path));
+        auto hash = GetHash(path);
+        ASSERT_TRUE(hash.has_value());
+        hashes_[name + flashed_slot_suffix] = *hash;
+    }
+
+    // Simulate shutting down the device after flash.
+    ASSERT_TRUE(UnmapAll());
+
+    // Simulate reboot. After reboot, init does first stage mount.
+    auto init = SnapshotManager::NewForFirstStageMount(
+            new TestDeviceInfo(fake_super, flashed_slot_suffix));
+    ASSERT_NE(init, nullptr);
+    if (init->NeedSnapshotsInFirstStageMount()) {
+        ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super"));
+    } else {
+        for (const auto& name : {"sys", "vnd"}) {
+            ASSERT_TRUE(CreateLogicalPartition(
+                    CreateLogicalPartitionParams{
+                            .block_device = fake_super,
+                            .metadata_slot = flashed_slot,
+                            .partition_name = name + flashed_slot_suffix,
+                            .timeout_ms = 1s,
+                            .partition_opener = opener_.get(),
+                    },
+                    &path));
+        }
+    }
+
+    // Check that the target partitions have the same content.
+    for (const auto& name : {"sys", "vnd"}) {
+        ASSERT_TRUE(IsPartitionUnchanged(name + flashed_slot_suffix));
+    }
+
+    // There should be no snapshot to merge.
+    auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, flashed_slot_suffix));
+    ASSERT_EQ(UpdateState::Cancelled, new_sm->InitiateMergeAndWait());
+
+    // Next OTA calls CancelUpdate no matter what.
+    ASSERT_TRUE(new_sm->CancelUpdate());
+}
+
+INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
+                         [](const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) {
+                             return "Flash"s + (std::get<0>(info.param) ? "New"s : "Old"s) +
+                                    "Slot"s + (std::get<1>(info.param) ? "After"s : "Before"s) +
+                                    "Merge"s;
+                         });
+
+}  // namespace snapshot
+}  // namespace android
+
+using namespace android::snapshot;
+
+bool Mkdir(const std::string& path) {
+    if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
+        std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
+        return false;
+    }
+    return true;
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    std::vector<std::string> paths = {
+            // clang-format off
+            "/data/gsi/ota/test",
+            "/data/gsi/ota/test/super",
+            "/metadata/gsi/ota/test",
+            "/metadata/gsi/ota/test/super",
+            "/metadata/ota/test",
+            "/metadata/ota/test/snapshots",
+            // clang-format on
+    };
+    for (const auto& path : paths) {
+        if (!Mkdir(path)) {
+            return 1;
+        }
+    }
+
+    // Create this once, otherwise, gsid will start/stop between each test.
+    test_device = new TestDeviceInfo();
+    sm = SnapshotManager::New(test_device);
+    if (!sm) {
+        std::cerr << "Could not create snapshot manager\n";
+        return 1;
+    }
+
+    // Clean up previous run.
+    MetadataMountedTest().TearDown();
+    SnapshotUpdateTest().Cleanup();
+    SnapshotTest().Cleanup();
+
+    // Use a separate image manager for our fake super partition.
+    auto super_images = IImageManager::Open("ota/test/super", 10s);
+    if (!super_images) {
+        std::cerr << "Could not create image manager\n";
+        return 1;
+    }
+
+    // Clean up any old copy.
+    DeleteBackingImage(super_images.get(), "fake-super");
+
+    // Create and map the fake super partition.
+    static constexpr int kImageFlags =
+            IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
+    if (!super_images->CreateBackingImage("fake-super", kSuperSize, kImageFlags)) {
+        std::cerr << "Could not create fake super partition\n";
+        return 1;
+    }
+    if (!super_images->MapImageDevice("fake-super", 10s, &fake_super)) {
+        std::cerr << "Could not map fake super partition\n";
+        return 1;
+    }
+    test_device->set_fake_super(fake_super);
+
+    auto result = RUN_ALL_TESTS();
+
+    DeleteBackingImage(super_images.get(), "fake-super");
+
+    return result;
+}
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
new file mode 100644
index 0000000..1bc0357
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -0,0 +1,102 @@
+//
+// 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 <sysexits.h>
+
+#include <chrono>
+#include <iostream>
+#include <map>
+
+#include <android-base/logging.h>
+#include <libsnapshot/snapshot.h>
+
+using namespace std::string_literals;
+
+int Usage() {
+    std::cerr << "snapshotctl: Control snapshots.\n"
+                 "Usage: snapshotctl [action] [flags]\n"
+                 "Actions:\n"
+                 "  dump\n"
+                 "    Print snapshot states.\n"
+                 "  merge [--logcat]\n"
+                 "    Initialize merge and wait for it to be completed.\n"
+                 "    If --logcat is specified, log to logcat. Otherwise, log to stdout.\n";
+    return EX_USAGE;
+}
+
+namespace android {
+namespace snapshot {
+
+bool DumpCmdHandler(int /*argc*/, char** argv) {
+    android::base::InitLogging(argv, &android::base::StderrLogger);
+    return SnapshotManager::New()->Dump(std::cout);
+}
+
+bool MergeCmdHandler(int argc, char** argv) {
+    auto begin = std::chrono::steady_clock::now();
+
+    bool log_to_logcat = false;
+    for (int i = 2; i < argc; ++i) {
+        if (argv[i] == "--logcat"s) {
+            log_to_logcat = true;
+        }
+    }
+    if (log_to_logcat) {
+        android::base::InitLogging(argv);
+    } else {
+        android::base::InitLogging(argv, &android::base::StdioLogger);
+    }
+
+    auto state = SnapshotManager::New()->InitiateMergeAndWait();
+
+    if (state == UpdateState::None) {
+        return true;
+    }
+    if (state == UpdateState::MergeCompleted) {
+        auto end = std::chrono::steady_clock::now();
+        auto passed = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
+        LOG(INFO) << "Snapshot merged in " << passed << " ms.";
+        return true;
+    }
+
+    LOG(ERROR) << "Snapshot failed to merge with state \"" << state << "\".";
+    return false;
+}
+
+static std::map<std::string, std::function<bool(int, char**)>> kCmdMap = {
+        // clang-format off
+        {"dump", DumpCmdHandler},
+        {"merge", MergeCmdHandler},
+        // clang-format on
+};
+
+}  // namespace snapshot
+}  // namespace android
+
+int main(int argc, char** argv) {
+    using namespace android::snapshot;
+    if (argc < 2) {
+        return Usage();
+    }
+
+    for (const auto& cmd : kCmdMap) {
+        if (cmd.first == argv[1]) {
+            return cmd.second(argc, argv) ? EX_OK : EX_SOFTWARE;
+        }
+    }
+
+    return Usage();
+}
diff --git a/fs_mgr/libsnapshot/snapshotctl.rc b/fs_mgr/libsnapshot/snapshotctl.rc
new file mode 100644
index 0000000..3ab0645
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapshotctl.rc
@@ -0,0 +1,2 @@
+on property:sys.boot_completed=1
+    exec_background - root root -- /system/bin/snapshotctl merge --logcat
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
new file mode 100644
index 0000000..f7f25af
--- /dev/null
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -0,0 +1,171 @@
+// 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 <libsnapshot/test_helpers.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+#include <openssl/sha.h>
+
+namespace android {
+namespace snapshot {
+
+using android::base::ReadFully;
+using android::base::unique_fd;
+using android::base::WriteFully;
+using android::fiemap::IImageManager;
+using testing::AssertionFailure;
+using testing::AssertionSuccess;
+
+void DeleteBackingImage(IImageManager* manager, const std::string& name) {
+    if (manager->IsImageMapped(name)) {
+        ASSERT_TRUE(manager->UnmapImageDevice(name));
+    }
+    if (manager->BackingImageExists(name)) {
+        ASSERT_TRUE(manager->DeleteBackingImage(name));
+    }
+}
+
+android::base::unique_fd TestPartitionOpener::Open(const std::string& partition_name,
+                                                   int flags) const {
+    if (partition_name == "super") {
+        return PartitionOpener::Open(fake_super_path_, flags);
+    }
+    return PartitionOpener::Open(partition_name, flags);
+}
+
+bool TestPartitionOpener::GetInfo(const std::string& partition_name,
+                                  android::fs_mgr::BlockDeviceInfo* info) const {
+    if (partition_name == "super") {
+        return PartitionOpener::GetInfo(fake_super_path_, info);
+    }
+    return PartitionOpener::GetInfo(partition_name, info);
+}
+
+std::string TestPartitionOpener::GetDeviceString(const std::string& partition_name) const {
+    if (partition_name == "super") {
+        return fake_super_path_;
+    }
+    return PartitionOpener::GetDeviceString(partition_name);
+}
+
+std::string ToHexString(const uint8_t* buf, size_t len) {
+    char lookup[] = "0123456789abcdef";
+    std::string out(len * 2 + 1, '\0');
+    char* outp = out.data();
+    for (; len > 0; len--, buf++) {
+        *outp++ = (char)lookup[*buf >> 4];
+        *outp++ = (char)lookup[*buf & 0xf];
+    }
+    return out;
+}
+
+bool WriteRandomData(const std::string& path, std::optional<size_t> expect_size,
+                     std::string* hash) {
+    unique_fd rand(open("/dev/urandom", O_RDONLY));
+    unique_fd fd(open(path.c_str(), O_WRONLY));
+
+    SHA256_CTX ctx;
+    if (hash) {
+        SHA256_Init(&ctx);
+    }
+
+    char buf[4096];
+    size_t total_written = 0;
+    while (!expect_size || total_written < *expect_size) {
+        ssize_t n = TEMP_FAILURE_RETRY(read(rand.get(), buf, sizeof(buf)));
+        if (n <= 0) return false;
+        if (!WriteFully(fd.get(), buf, n)) {
+            if (errno == ENOSPC) {
+                break;
+            }
+            PLOG(ERROR) << "Cannot write " << path;
+            return false;
+        }
+        total_written += n;
+        if (hash) {
+            SHA256_Update(&ctx, buf, n);
+        }
+    }
+
+    if (expect_size && total_written != *expect_size) {
+        PLOG(ERROR) << "Written " << total_written << " bytes, expected " << *expect_size;
+        return false;
+    }
+
+    if (hash) {
+        uint8_t out[32];
+        SHA256_Final(out, &ctx);
+        *hash = ToHexString(out, sizeof(out));
+    }
+    return true;
+}
+
+std::optional<std::string> GetHash(const std::string& path) {
+    std::string content;
+    if (!android::base::ReadFileToString(path, &content, true)) {
+        PLOG(ERROR) << "Cannot access " << path;
+        return std::nullopt;
+    }
+    SHA256_CTX ctx;
+    SHA256_Init(&ctx);
+    SHA256_Update(&ctx, content.c_str(), content.size());
+    uint8_t out[32];
+    SHA256_Final(out, &ctx);
+    return ToHexString(out, sizeof(out));
+}
+
+AssertionResult FillFakeMetadata(MetadataBuilder* builder, const DeltaArchiveManifest& manifest,
+                                 const std::string& suffix) {
+    for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
+        if (!builder->AddGroup(group.name() + suffix, group.size())) {
+            return AssertionFailure()
+                   << "Cannot add group " << group.name() << " with size " << group.size();
+        }
+        for (const auto& partition_name : group.partition_names()) {
+            auto p = builder->AddPartition(partition_name + suffix, group.name() + suffix,
+                                           0 /* attr */);
+            if (!p) {
+                return AssertionFailure() << "Cannot add partition " << partition_name + suffix
+                                          << " to group " << group.name() << suffix;
+            }
+        }
+    }
+    for (const auto& partition : manifest.partitions()) {
+        auto p = builder->FindPartition(partition.partition_name() + suffix);
+        if (!p) {
+            return AssertionFailure() << "Cannot resize partition " << partition.partition_name()
+                                      << suffix << "; it is not found.";
+        }
+        if (!builder->ResizePartition(p, partition.new_partition_info().size())) {
+            return AssertionFailure()
+                   << "Cannot resize partition " << partition.partition_name() << suffix
+                   << " to size " << partition.new_partition_info().size();
+        }
+    }
+    return AssertionSuccess();
+}
+
+void SetSize(PartitionUpdate* partition_update, uint64_t size) {
+    partition_update->mutable_new_partition_info()->set_size(size);
+}
+
+uint64_t GetSize(PartitionUpdate* partition_update) {
+    return partition_update->mutable_new_partition_info()->size();
+}
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
new file mode 100644
index 0000000..fa1d7f0
--- /dev/null
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -0,0 +1,156 @@
+// 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 "utility.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fs_mgr/roots.h>
+
+using android::dm::kSectorSize;
+using android::fs_mgr::EnsurePathMounted;
+using android::fs_mgr::EnsurePathUnmounted;
+using android::fs_mgr::Fstab;
+using android::fs_mgr::GetEntryForPath;
+using android::fs_mgr::MetadataBuilder;
+using android::fs_mgr::Partition;
+using android::fs_mgr::ReadDefaultFstab;
+
+namespace android {
+namespace snapshot {
+
+void AutoDevice::Release() {
+    name_.clear();
+}
+
+AutoDeviceList::~AutoDeviceList() {
+    // Destroy devices in the reverse order because newer devices may have dependencies
+    // on older devices.
+    for (auto it = devices_.rbegin(); it != devices_.rend(); ++it) {
+        it->reset();
+    }
+}
+
+void AutoDeviceList::Release() {
+    for (auto&& p : devices_) {
+        p->Release();
+    }
+}
+
+AutoUnmapDevice::~AutoUnmapDevice() {
+    if (name_.empty()) return;
+    if (!dm_->DeleteDeviceIfExists(name_)) {
+        LOG(ERROR) << "Failed to auto unmap device " << name_;
+    }
+}
+
+AutoUnmapImage::~AutoUnmapImage() {
+    if (name_.empty()) return;
+    if (!images_->UnmapImageIfExists(name_)) {
+        LOG(ERROR) << "Failed to auto unmap cow image " << name_;
+    }
+}
+
+std::vector<Partition*> ListPartitionsWithSuffix(MetadataBuilder* builder,
+                                                 const std::string& suffix) {
+    std::vector<Partition*> ret;
+    for (const auto& group : builder->ListGroups()) {
+        for (auto* partition : builder->ListPartitionsInGroup(group)) {
+            if (!base::EndsWith(partition->name(), suffix)) {
+                continue;
+            }
+            ret.push_back(partition);
+        }
+    }
+    return ret;
+}
+
+AutoDeleteSnapshot::~AutoDeleteSnapshot() {
+    if (!name_.empty() && !manager_->DeleteSnapshot(lock_, name_)) {
+        LOG(ERROR) << "Failed to auto delete snapshot " << name_;
+    }
+}
+
+bool InitializeCow(const std::string& device) {
+    // When the kernel creates a persistent dm-snapshot, it requires a CoW file
+    // to store the modifications. The kernel interface does not specify how
+    // the CoW is used, and there is no standard associated.
+    // By looking at the current implementation, the CoW file is treated as:
+    // - a _NEW_ snapshot if its first 32 bits are zero, so the newly created
+    // dm-snapshot device will look like a perfect copy of the origin device;
+    // - an _EXISTING_ snapshot if the first 32 bits are equal to a
+    // kernel-specified magic number and the CoW file metadata is set as valid,
+    // so it can be used to resume the last state of a snapshot device;
+    // - an _INVALID_ snapshot otherwise.
+    // To avoid zero-filling the whole CoW file when a new dm-snapshot is
+    // created, here we zero-fill only the first chunk to be compliant with
+    // lvm.
+    constexpr ssize_t kDmSnapZeroFillSize = kSectorSize * kSnapshotChunkSize;
+
+    std::vector<uint8_t> zeros(kDmSnapZeroFillSize, 0);
+    android::base::unique_fd fd(open(device.c_str(), O_WRONLY | O_BINARY));
+    if (fd < 0) {
+        PLOG(ERROR) << "Can't open COW device: " << device;
+        return false;
+    }
+
+    LOG(INFO) << "Zero-filling COW device: " << device;
+    if (!android::base::WriteFully(fd, zeros.data(), kDmSnapZeroFillSize)) {
+        PLOG(ERROR) << "Can't zero-fill COW device for " << device;
+        return false;
+    }
+    return true;
+}
+
+std::unique_ptr<AutoUnmountDevice> AutoUnmountDevice::New(const std::string& path) {
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        LOG(ERROR) << "Cannot read default fstab";
+        return nullptr;
+    }
+
+    if (GetEntryForPath(&fstab, path) == nullptr) {
+        LOG(INFO) << "EnsureMetadataMounted can't find entry for " << path << ", skipping";
+        return std::unique_ptr<AutoUnmountDevice>(new AutoUnmountDevice("", {}));
+    }
+
+    if (!EnsurePathMounted(&fstab, path)) {
+        LOG(ERROR) << "Cannot mount " << path;
+        return nullptr;
+    }
+    return std::unique_ptr<AutoUnmountDevice>(new AutoUnmountDevice(path, std::move(fstab)));
+}
+
+AutoUnmountDevice::~AutoUnmountDevice() {
+    if (name_.empty()) return;
+    if (!EnsurePathUnmounted(&fstab_, name_)) {
+        LOG(ERROR) << "Cannot unmount " << name_;
+    }
+}
+
+bool WriteStringToFileAtomic(const std::string& content, const std::string& path) {
+    std::string tmp_path = path + ".tmp";
+    if (!android::base::WriteStringToFile(content, tmp_path)) {
+        return false;
+    }
+    if (rename(tmp_path.c_str(), path.c_str()) == -1) {
+        PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;
+        return false;
+    }
+    return true;
+}
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
new file mode 100644
index 0000000..5cc572e
--- /dev/null
+++ b/fs_mgr/libsnapshot/utility.h
@@ -0,0 +1,123 @@
+// 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 <functional>
+#include <string>
+
+#include <android-base/macros.h>
+#include <fstab/fstab.h>
+#include <libdm/dm.h>
+#include <libfiemap/image_manager.h>
+#include <liblp/builder.h>
+#include <libsnapshot/snapshot.h>
+#include <update_engine/update_metadata.pb.h>
+
+#include <libsnapshot/auto_device.h>
+
+namespace android {
+namespace snapshot {
+
+// Unit is sectors, this is a 4K chunk.
+static constexpr uint32_t kSnapshotChunkSize = 8;
+
+// A list of devices we created along the way.
+// - Whenever a device is created that is subject to GC'ed at the end of
+//   this function, add it to this list.
+// - If any error has occurred, the list is destroyed, and all these devices
+//   are cleaned up.
+// - Upon success, Release() should be called so that the created devices
+//   are kept.
+struct AutoDeviceList {
+    ~AutoDeviceList();
+    template <typename T, typename... Args>
+    void EmplaceBack(Args&&... args) {
+        devices_.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
+    }
+    void Release();
+
+  private:
+    std::vector<std::unique_ptr<AutoDevice>> devices_;
+};
+
+// Automatically unmap a device upon deletion.
+struct AutoUnmapDevice : AutoDevice {
+    // On destruct, delete |name| from device mapper.
+    AutoUnmapDevice(android::dm::DeviceMapper* dm, const std::string& name)
+        : AutoDevice(name), dm_(dm) {}
+    AutoUnmapDevice(AutoUnmapDevice&& other) = default;
+    ~AutoUnmapDevice();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(AutoUnmapDevice);
+    android::dm::DeviceMapper* dm_ = nullptr;
+};
+
+// Automatically unmap an image upon deletion.
+struct AutoUnmapImage : AutoDevice {
+    // On destruct, delete |name| from image manager.
+    AutoUnmapImage(android::fiemap::IImageManager* images, const std::string& name)
+        : AutoDevice(name), images_(images) {}
+    AutoUnmapImage(AutoUnmapImage&& other) = default;
+    ~AutoUnmapImage();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(AutoUnmapImage);
+    android::fiemap::IImageManager* images_ = nullptr;
+};
+
+// Automatically deletes a snapshot. |name| should be the name of the partition, e.g. "system_a".
+// Client is responsible for maintaining the lifetime of |manager| and |lock|.
+struct AutoDeleteSnapshot : AutoDevice {
+    AutoDeleteSnapshot(SnapshotManager* manager, SnapshotManager::LockedFile* lock,
+                       const std::string& name)
+        : AutoDevice(name), manager_(manager), lock_(lock) {}
+    AutoDeleteSnapshot(AutoDeleteSnapshot&& other);
+    ~AutoDeleteSnapshot();
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(AutoDeleteSnapshot);
+    SnapshotManager* manager_ = nullptr;
+    SnapshotManager::LockedFile* lock_ = nullptr;
+};
+
+struct AutoUnmountDevice : AutoDevice {
+    // Empty object that does nothing.
+    AutoUnmountDevice() : AutoDevice("") {}
+    static std::unique_ptr<AutoUnmountDevice> New(const std::string& path);
+    ~AutoUnmountDevice();
+
+  private:
+    AutoUnmountDevice(const std::string& path, android::fs_mgr::Fstab&& fstab)
+        : AutoDevice(path), fstab_(std::move(fstab)) {}
+    android::fs_mgr::Fstab fstab_;
+};
+
+// Return a list of partitions in |builder| with the name ending in |suffix|.
+std::vector<android::fs_mgr::Partition*> ListPartitionsWithSuffix(
+        android::fs_mgr::MetadataBuilder* builder, const std::string& suffix);
+
+// Initialize a device before using it as the COW device for a dm-snapshot device.
+bool InitializeCow(const std::string& device);
+
+// "Atomically" write string to file. This is done by a series of actions:
+// 1. Write to path + ".tmp"
+// 2. Move temporary file to path using rename()
+// Note that rename() is an atomic operation. This function may not work properly if there
+// is an open fd to |path|, because that fd has an old view of the file.
+bool WriteStringToFileAtomic(const std::string& content, const std::string& path);
+
+}  // namespace snapshot
+}  // namespace android
diff --git a/fs_mgr/libstorage_literals/Android.bp b/fs_mgr/libstorage_literals/Android.bp
new file mode 100644
index 0000000..11611dd
--- /dev/null
+++ b/fs_mgr/libstorage_literals/Android.bp
@@ -0,0 +1,6 @@
+
+cc_library_headers {
+    name: "libstorage_literals_headers",
+    host_supported: true,
+    export_include_dirs: ["."],
+}
diff --git a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
new file mode 100644
index 0000000..ac0dfbd
--- /dev/null
+++ b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h
@@ -0,0 +1,77 @@
+// 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 <stdint.h>
+#include <stdlib.h>
+
+namespace android {
+namespace storage_literals {
+
+template <size_t Power>
+struct Size {
+    static constexpr size_t power = Power;
+    explicit constexpr Size(uint64_t count) : value_(count) {}
+
+    constexpr uint64_t bytes() const { return value_ << power; }
+    constexpr uint64_t count() const { return value_; }
+    constexpr operator uint64_t() const { return bytes(); }
+
+  private:
+    uint64_t value_;
+};
+
+using B = Size<0>;
+using KiB = Size<10>;
+using MiB = Size<20>;
+using GiB = Size<30>;
+
+constexpr B operator""_B(unsigned long long v) {  // NOLINT
+    return B{v};
+}
+
+constexpr KiB operator""_KiB(unsigned long long v) {  // NOLINT
+    return KiB{v};
+}
+
+constexpr MiB operator""_MiB(unsigned long long v) {  // NOLINT
+    return MiB{v};
+}
+
+constexpr GiB operator""_GiB(unsigned long long v) {  // NOLINT
+    return GiB{v};
+}
+
+template <typename Dest, typename Src>
+constexpr Dest size_cast(Src src) {
+    if (Src::power < Dest::power) {
+        return Dest(src.count() >> (Dest::power - Src::power));
+    }
+    if (Src::power > Dest::power) {
+        return Dest(src.count() << (Src::power - Dest::power));
+    }
+    return Dest(src.count());
+}
+
+static_assert(1_B == 1);
+static_assert(1_KiB == 1 << 10);
+static_assert(1_MiB == 1 << 20);
+static_assert(1_GiB == 1 << 30);
+static_assert(size_cast<KiB>(1_B).count() == 0);
+static_assert(size_cast<KiB>(1024_B).count() == 1);
+static_assert(size_cast<KiB>(1_MiB).count() == 1024);
+
+}  // namespace storage_literals
+}  // namespace android
diff --git a/fs_mgr/libvbmeta/Android.bp b/fs_mgr/libvbmeta/Android.bp
new file mode 100644
index 0000000..937e0f3
--- /dev/null
+++ b/fs_mgr/libvbmeta/Android.bp
@@ -0,0 +1,52 @@
+//
+// 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.
+//
+
+libvbmeta_lib_deps = [
+    "libbase",
+    "libcrypto",
+]
+
+cc_library {
+    name: "libvbmeta",
+    host_supported: true,
+    srcs: [
+        "builder.cpp",
+        "reader.cpp",
+        "utility.cpp",
+        "writer.cpp",
+    ],
+    shared_libs: [
+        "liblog",
+    ] + libvbmeta_lib_deps,
+    export_include_dirs: ["include"],
+}
+
+cc_test_host {
+    name: "libvbmeta_test",
+    static_libs: [
+        "libsparse",
+        "libvbmeta",
+        "libz",
+    ] + libvbmeta_lib_deps,
+    srcs: [
+        "builder_test.cpp",
+        "super_vbmeta_test.cpp",
+    ],
+    required: [
+        "avbtool",
+        "vbmake",
+    ],
+}
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/builder.cpp b/fs_mgr/libvbmeta/builder.cpp
new file mode 100644
index 0000000..a901a4f
--- /dev/null
+++ b/fs_mgr/libvbmeta/builder.cpp
@@ -0,0 +1,214 @@
+/*
+ * 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 "builder.h"
+
+#include <android-base/file.h>
+#include <openssl/sha.h>
+
+#include "reader.h"
+#include "utility.h"
+#include "writer.h"
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::base::unique_fd;
+
+namespace android {
+namespace fs_mgr {
+
+SuperVBMetaBuilder::SuperVBMetaBuilder() {}
+
+SuperVBMetaBuilder::SuperVBMetaBuilder(const int super_vbmeta_fd,
+                                       const std::map<std::string, std::string>& images_path)
+    : super_vbmeta_fd_(super_vbmeta_fd), images_path_(images_path) {}
+
+Result<void> SuperVBMetaBuilder::Build() {
+    for (const auto& [vbmeta_name, file_path] : images_path_) {
+        Result<std::string> content = ReadVBMetaImageFromFile(file_path);
+        if (!content) {
+            return content.error();
+        }
+
+        Result<uint8_t> vbmeta_index = AddVBMetaImage(vbmeta_name);
+        if (!vbmeta_index) {
+            return vbmeta_index.error();
+        }
+
+        Result<void> rv_export_vbmeta_image =
+                ExportVBMetaImageToFile(vbmeta_index.value(), content.value());
+        if (!rv_export_vbmeta_image) {
+            return rv_export_vbmeta_image;
+        }
+    }
+    return {};
+}
+
+Result<std::string> SuperVBMetaBuilder::ReadVBMetaImageFromFile(const std::string& file) {
+    unique_fd source_fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (source_fd < 0) {
+        return ErrnoError() << "Couldn't open vbmeta image file " << file;
+    }
+
+    Result<uint64_t> file_size = GetFileSize(source_fd);
+    if (!file_size) {
+        return file_size.error();
+    }
+
+    if (file_size.value() > VBMETA_IMAGE_MAX_SIZE) {
+        return Error() << "vbmeta image file size " << file_size.value() << " is too large";
+    }
+
+    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(VBMETA_IMAGE_MAX_SIZE);
+    if (!android::base::ReadFully(source_fd, buffer.get(), file_size.value())) {
+        return ErrnoError() << "Couldn't read vbmeta image file " << file;
+    }
+
+    return std::string(reinterpret_cast<const char*>(buffer.get()), VBMETA_IMAGE_MAX_SIZE);
+}
+
+Result<uint8_t> SuperVBMetaBuilder::GetEmptySlot() {
+    for (uint8_t i = 0; i < VBMETA_IMAGE_MAX_NUM; ++i) {
+        if ((table_.header.in_use & (1 << i)) == 0) return i;
+    }
+    return Error() << "There isn't empty slot in super vbmeta";
+}
+
+Result<uint8_t> SuperVBMetaBuilder::AddVBMetaImage(const std::string& vbmeta_name) {
+    auto desc = std::find_if(
+            table_.descriptors.begin(), table_.descriptors.end(),
+            [&vbmeta_name](const auto& entry) { return entry.vbmeta_name == vbmeta_name; });
+
+    uint8_t slot_number = 0;
+    if (desc != table_.descriptors.end()) {
+        slot_number = desc->vbmeta_index;
+    } else {
+        Result<uint8_t> new_slot = GetEmptySlot();
+        if (!new_slot) {
+            return new_slot;
+        }
+        slot_number = new_slot.value();
+
+        // insert new descriptor into table
+        InternalVBMetaDescriptor new_desc;
+        new_desc.vbmeta_index = slot_number;
+        new_desc.vbmeta_name_length = vbmeta_name.length();
+        new_desc.vbmeta_name = vbmeta_name;
+        memset(new_desc.reserved, 0, sizeof(new_desc.reserved));
+        table_.descriptors.emplace_back(std::move(new_desc));
+
+        // mark slot as in use
+        table_.header.in_use |= (1 << slot_number);
+    }
+
+    return slot_number;
+}
+
+void SuperVBMetaBuilder::DeleteVBMetaImage(const std::string& vbmeta_name) {
+    auto desc = std::find_if(
+            table_.descriptors.begin(), table_.descriptors.end(),
+            [&vbmeta_name](const auto& entry) { return entry.vbmeta_name == vbmeta_name; });
+
+    if (desc != table_.descriptors.end()) {
+        // mark slot as not in use
+        table_.header.in_use &= ~(1 << desc->vbmeta_index);
+
+        // erase descriptor in table
+        table_.descriptors.erase(desc);
+    }
+}
+
+std::unique_ptr<VBMetaTable> SuperVBMetaBuilder::ExportVBMetaTable() {
+    // calculate descriptors size
+    uint32_t descriptors_size = 0;
+    for (const auto& desc : table_.descriptors) {
+        descriptors_size += SUPER_VBMETA_DESCRIPTOR_SIZE + desc.vbmeta_name_length * sizeof(char);
+    }
+
+    // export header
+    table_.header.magic = SUPER_VBMETA_MAGIC;
+    table_.header.major_version = SUPER_VBMETA_MAJOR_VERSION;
+    table_.header.minor_version = SUPER_VBMETA_MINOR_VERSION;
+    table_.header.header_size = SUPER_VBMETA_HEADER_SIZE;
+    table_.header.total_size = SUPER_VBMETA_HEADER_SIZE + descriptors_size;
+    memset(table_.header.checksum, 0, sizeof(table_.header.checksum));
+    table_.header.descriptors_size = descriptors_size;
+    memset(table_.header.reserved, 0, sizeof(table_.header.reserved));
+    std::string serialized_table = SerializeVBMetaTable(table_);
+    ::SHA256(reinterpret_cast<const uint8_t*>(serialized_table.c_str()), table_.header.total_size,
+             &table_.header.checksum[0]);
+
+    return std::make_unique<VBMetaTable>(table_);
+}
+
+Result<void> SuperVBMetaBuilder::ExportVBMetaTableToFile() {
+    std::unique_ptr<VBMetaTable> table = ExportVBMetaTable();
+
+    std::string serialized_table = SerializeVBMetaTable(*table);
+
+    android::base::Result<void> rv_write_primary_vbmeta_table =
+            WritePrimaryVBMetaTable(super_vbmeta_fd_, serialized_table);
+    if (!rv_write_primary_vbmeta_table) {
+        return rv_write_primary_vbmeta_table;
+    }
+
+    android::base::Result<void> rv_write_backup_vbmeta_table =
+            WriteBackupVBMetaTable(super_vbmeta_fd_, serialized_table);
+    return rv_write_backup_vbmeta_table;
+}
+
+Result<void> SuperVBMetaBuilder::ExportVBMetaImageToFile(const uint8_t vbmeta_index,
+                                                         const std::string& vbmeta_image) {
+    Result<void> rv_write_vbmeta_image =
+            WriteVBMetaImage(super_vbmeta_fd_, vbmeta_index, vbmeta_image);
+    if (!rv_write_vbmeta_image) {
+        return rv_write_vbmeta_image;
+    }
+
+    Result<void> rv_validate_vbmeta_image =
+            ValidateVBMetaImage(super_vbmeta_fd_, vbmeta_index, vbmeta_image);
+    return rv_validate_vbmeta_image;
+}
+
+bool WriteToSuperVBMetaFile(const std::string& super_vbmeta_file,
+                            const std::map<std::string, std::string>& images_path) {
+    unique_fd super_vbmeta_fd(TEMP_FAILURE_RETRY(
+            open(super_vbmeta_file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0644)));
+    if (super_vbmeta_fd < 0) {
+        PERROR << "Couldn't open super vbmeta file " << super_vbmeta_file;
+        return false;
+    }
+
+    SuperVBMetaBuilder builder(super_vbmeta_fd, images_path);
+
+    Result<void> rv_build = builder.Build();
+    if (!rv_build) {
+        LERROR << rv_build.error();
+        return false;
+    }
+
+    Result<void> rv_export = builder.ExportVBMetaTableToFile();
+    if (!rv_export) {
+        LERROR << rv_export.error();
+        return false;
+    }
+
+    return true;
+}
+
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/builder.h b/fs_mgr/libvbmeta/builder.h
new file mode 100644
index 0000000..58ea36a
--- /dev/null
+++ b/fs_mgr/libvbmeta/builder.h
@@ -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.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+
+#include <android-base/result.h>
+
+#include "super_vbmeta_format.h"
+
+namespace android {
+namespace fs_mgr {
+
+class SuperVBMetaBuilder {
+  public:
+    SuperVBMetaBuilder();
+    SuperVBMetaBuilder(const int super_vbmeta_fd,
+                       const std::map<std::string, std::string>& images_path);
+    android::base::Result<void> Build();
+    android::base::Result<std::string> ReadVBMetaImageFromFile(const std::string& file);
+    // It adds the vbmeta image in super_vbmeta and returns the index
+    // (which has the same meaning with vbmeta_index of VBMetaDescriptor).
+    android::base::Result<uint8_t> AddVBMetaImage(const std::string& vbmeta_name);
+    void DeleteVBMetaImage(const std::string& vbmeta_name);
+    std::unique_ptr<VBMetaTable> ExportVBMetaTable();
+    android::base::Result<void> ExportVBMetaTableToFile();
+    android::base::Result<void> ExportVBMetaImageToFile(const uint8_t vbmeta_index,
+                                                        const std::string& vbmeta_image);
+
+  private:
+    android::base::Result<uint8_t> GetEmptySlot();
+
+    int super_vbmeta_fd_;
+    VBMetaTable table_;
+    // Maps vbmeta image name to vbmeta image file path.
+    std::map<std::string, std::string> images_path_;
+};
+
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/builder_test.cpp b/fs_mgr/libvbmeta/builder_test.cpp
new file mode 100644
index 0000000..9a015fd
--- /dev/null
+++ b/fs_mgr/libvbmeta/builder_test.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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 "builder.h"
+#include "super_vbmeta_format.h"
+
+using android::base::Result;
+using android::fs_mgr::SuperVBMetaBuilder;
+
+TEST(BuilderTest, VBMetaTableBasic) {
+    std::unique_ptr<SuperVBMetaBuilder> builder = std::make_unique<SuperVBMetaBuilder>();
+    ASSERT_NE(builder, nullptr);
+
+    Result<uint8_t> vbmeta_index = builder->AddVBMetaImage("vbmeta" /* vbmeta_name */
+    );
+    EXPECT_TRUE(vbmeta_index);
+
+    Result<uint8_t> vbmeta_system_slot = builder->AddVBMetaImage("vbmeta_system" /* vbmeta_name */
+    );
+    EXPECT_TRUE(vbmeta_system_slot);
+
+    Result<uint8_t> vbmeta_vendor_slot = builder->AddVBMetaImage("vbmeta_vendor" /* vbmeta_name */
+    );
+    EXPECT_TRUE(vbmeta_vendor_slot);
+
+    builder->DeleteVBMetaImage("vbmeta_system" /* vbmeta_name */
+    );
+
+    Result<uint8_t> vbmeta_product_slot = builder->AddVBMetaImage("vbmeta_product" /* vbmeta_name */
+    );
+    EXPECT_TRUE(vbmeta_product_slot);
+
+    std::unique_ptr<VBMetaTable> table = builder->ExportVBMetaTable();
+    ASSERT_NE(table, nullptr);
+
+    // check for vbmeta table header
+    EXPECT_EQ(table->header.magic, SUPER_VBMETA_MAGIC);
+    EXPECT_EQ(table->header.major_version, SUPER_VBMETA_MAJOR_VERSION);
+    EXPECT_EQ(table->header.minor_version, SUPER_VBMETA_MINOR_VERSION);
+    EXPECT_EQ(table->header.header_size, SUPER_VBMETA_HEADER_SIZE);
+    EXPECT_EQ(table->header.total_size,
+              SUPER_VBMETA_HEADER_SIZE + SUPER_VBMETA_DESCRIPTOR_SIZE * 3 + 33);
+    EXPECT_EQ(table->header.descriptors_size, SUPER_VBMETA_DESCRIPTOR_SIZE * 3 + 33);
+
+    // Test for vbmeta table descriptors
+    EXPECT_EQ(table->descriptors.size(), 3);
+
+    EXPECT_EQ(table->descriptors[0].vbmeta_index, 0);
+    EXPECT_EQ(table->descriptors[0].vbmeta_name_length, 6);
+    for (int i = 0; i < sizeof(table->descriptors[0].reserved); i++)
+        EXPECT_EQ(table->descriptors[0].reserved[i], 0);
+    EXPECT_EQ(table->descriptors[0].vbmeta_name, "vbmeta");
+
+    EXPECT_EQ(table->descriptors[1].vbmeta_index, 2);
+    EXPECT_EQ(table->descriptors[1].vbmeta_name_length, 13);
+    for (int i = 0; i < sizeof(table->descriptors[1].reserved); i++)
+        EXPECT_EQ(table->descriptors[1].reserved[i], 0);
+    EXPECT_EQ(table->descriptors[1].vbmeta_name, "vbmeta_vendor");
+
+    EXPECT_EQ(table->descriptors[2].vbmeta_index, 1);
+    EXPECT_EQ(table->descriptors[2].vbmeta_name_length, 14);
+    for (int i = 0; i < sizeof(table->descriptors[2].reserved); i++)
+        EXPECT_EQ(table->descriptors[2].reserved[i], 0);
+    EXPECT_EQ(table->descriptors[2].vbmeta_name, "vbmeta_product");
+}
\ No newline at end of file
diff --git a/fs_mgr/libfiemap_writer/utility.h b/fs_mgr/libvbmeta/include/libvbmeta/libvbmeta.h
similarity index 69%
rename from fs_mgr/libfiemap_writer/utility.h
rename to fs_mgr/libvbmeta/include/libvbmeta/libvbmeta.h
index 2d418da..ab7ba73 100644
--- a/fs_mgr/libfiemap_writer/utility.h
+++ b/fs_mgr/libvbmeta/include/libvbmeta/libvbmeta.h
@@ -16,15 +16,14 @@
 
 #pragma once
 
+#include <map>
 #include <string>
 
 namespace android {
-namespace fiemap_writer {
+namespace fs_mgr {
 
-// Given a file that will be created, determine the maximum size its containing
-// filesystem allows. Note this is a theoretical maximum size; free space is
-// ignored entirely.
-uint64_t DetermineMaximumFileSize(const std::string& file_path);
+bool WriteToSuperVBMetaFile(const std::string& super_vbmeta_file,
+                            const std::map<std::string, std::string>& images_path);
 
-}  // namespace fiemap_writer
-}  // namespace android
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/reader.cpp b/fs_mgr/libvbmeta/reader.cpp
new file mode 100644
index 0000000..212d186
--- /dev/null
+++ b/fs_mgr/libvbmeta/reader.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 "reader.h"
+
+#include <android-base/file.h>
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+namespace fs_mgr {
+
+Result<void> LoadAndVerifySuperVBMetaHeader(const void* buffer, SuperVBMetaHeader* header) {
+    memcpy(header, buffer, sizeof(*header));
+
+    // Do basic validation of super vbmeta.
+    if (header->magic != SUPER_VBMETA_MAGIC) {
+        return Error() << "Super VBMeta has invalid magic value";
+    }
+
+    // Check that the version is compatible.
+    if (header->major_version != SUPER_VBMETA_MAJOR_VERSION ||
+        header->minor_version > SUPER_VBMETA_MINOR_VERSION) {
+        return Error() << "Super VBMeta has incompatible version";
+    }
+    return {};
+}
+
+void LoadVBMetaDescriptors(const void* buffer, uint32_t size,
+                           std::vector<InternalVBMetaDescriptor>* descriptors) {
+    for (int p = 0; p < size;) {
+        InternalVBMetaDescriptor descriptor;
+        memcpy(&descriptor, (char*)buffer + p, SUPER_VBMETA_DESCRIPTOR_SIZE);
+        p += SUPER_VBMETA_DESCRIPTOR_SIZE;
+
+        descriptor.vbmeta_name = std::string((char*)buffer + p, descriptor.vbmeta_name_length);
+        p += descriptor.vbmeta_name_length;
+
+        descriptors->emplace_back(std::move(descriptor));
+    }
+}
+
+Result<void> ReadVBMetaTable(int fd, uint64_t offset, VBMetaTable* table) {
+    std::unique_ptr<uint8_t[]> header_buffer =
+            std::make_unique<uint8_t[]>(SUPER_VBMETA_HEADER_SIZE);
+    if (!android::base::ReadFullyAtOffset(fd, header_buffer.get(), SUPER_VBMETA_HEADER_SIZE,
+                                          offset)) {
+        return ErrnoError() << "Couldn't read super vbmeta header at offset " << offset;
+    }
+
+    Result<void> rv_header = LoadAndVerifySuperVBMetaHeader(header_buffer.get(), &table->header);
+    if (!rv_header) {
+        return rv_header;
+    }
+
+    const uint64_t descriptors_offset = offset + table->header.header_size;
+    std::unique_ptr<uint8_t[]> descriptors_buffer =
+            std::make_unique<uint8_t[]>(table->header.descriptors_size);
+    if (!android::base::ReadFullyAtOffset(fd, descriptors_buffer.get(),
+                                          table->header.descriptors_size, descriptors_offset)) {
+        return ErrnoError() << "Couldn't read super vbmeta descriptors at offset "
+                            << descriptors_offset;
+    }
+
+    LoadVBMetaDescriptors(descriptors_buffer.get(), table->header.descriptors_size,
+                          &table->descriptors);
+    return {};
+}
+
+Result<void> ReadPrimaryVBMetaTable(int fd, VBMetaTable* table) {
+    uint64_t offset = PRIMARY_SUPER_VBMETA_TABLE_OFFSET;
+    return ReadVBMetaTable(fd, offset, table);
+}
+
+Result<void> ReadBackupVBMetaTable(int fd, VBMetaTable* table) {
+    uint64_t offset = BACKUP_SUPER_VBMETA_TABLE_OFFSET;
+    return ReadVBMetaTable(fd, offset, table);
+}
+
+Result<std::string> ReadVBMetaImage(int fd, int slot) {
+    const uint64_t offset = 2 * SUPER_VBMETA_TABLE_MAX_SIZE + slot * VBMETA_IMAGE_MAX_SIZE;
+    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(VBMETA_IMAGE_MAX_SIZE);
+    if (!android::base::ReadFullyAtOffset(fd, buffer.get(), VBMETA_IMAGE_MAX_SIZE, offset)) {
+        return ErrnoError() << "Couldn't read vbmeta image at offset " << offset;
+    }
+    return std::string(reinterpret_cast<char*>(buffer.get()), VBMETA_IMAGE_MAX_SIZE);
+}
+
+Result<void> ValidateVBMetaImage(int super_vbmeta_fd, int vbmeta_index,
+                                 const std::string& vbmeta_image) {
+    Result<std::string> content = ReadVBMetaImage(super_vbmeta_fd, vbmeta_index);
+    if (!content) {
+        return content.error();
+    }
+
+    if (vbmeta_image != content.value()) {
+        return Error() << "VBMeta Image in Super VBMeta differ from the original one.";
+    }
+    return {};
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/libvbmeta/reader.h b/fs_mgr/libvbmeta/reader.h
new file mode 100644
index 0000000..f0997ff
--- /dev/null
+++ b/fs_mgr/libvbmeta/reader.h
@@ -0,0 +1,34 @@
+/*
+ * 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 <android-base/result.h>
+
+#include "super_vbmeta_format.h"
+
+namespace android {
+namespace fs_mgr {
+
+android::base::Result<void> ReadPrimaryVBMetaTable(int fd, VBMetaTable* table);
+android::base::Result<void> ReadBackupVBMetaTable(int fd, VBMetaTable* table);
+android::base::Result<std::string> ReadVBMetaImage(int fd, int slot);
+
+android::base::Result<void> ValidateVBMetaImage(int super_vbmeta_fd, int vbmeta_index,
+                                                const std::string& vbmeta_image);
+
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libfiemap_writer/utility.h b/fs_mgr/libvbmeta/super_vbmeta_format.h
similarity index 62%
copy from fs_mgr/libfiemap_writer/utility.h
copy to fs_mgr/libvbmeta/super_vbmeta_format.h
index 2d418da..c62a2dd 100644
--- a/fs_mgr/libfiemap_writer/utility.h
+++ b/fs_mgr/libvbmeta/super_vbmeta_format.h
@@ -14,17 +14,21 @@
  * limitations under the License.
  */
 
+/* This .h file is intended for CPP clients (usually fastbootd, recovery and update_engine)  */
+
 #pragma once
 
 #include <string>
+#include <vector>
 
-namespace android {
-namespace fiemap_writer {
+#include "super_vbmeta_format_c.h"
 
-// Given a file that will be created, determine the maximum size its containing
-// filesystem allows. Note this is a theoretical maximum size; free space is
-// ignored entirely.
-uint64_t DetermineMaximumFileSize(const std::string& file_path);
+struct InternalVBMetaDescriptor : VBMetaDescriptor {
+    /*  64: The vbmeta image's name */
+    std::string vbmeta_name;
+};
 
-}  // namespace fiemap_writer
-}  // namespace android
+struct VBMetaTable {
+    SuperVBMetaHeader header;
+    std::vector<InternalVBMetaDescriptor> descriptors;
+};
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/super_vbmeta_format_c.h b/fs_mgr/libvbmeta/super_vbmeta_format_c.h
new file mode 100644
index 0000000..6d79801
--- /dev/null
+++ b/fs_mgr/libvbmeta/super_vbmeta_format_c.h
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+/* This .h file is intended for C clients (usually bootloader).  */
+
+#pragma once
+
+#include <stdint.h>
+
+/* Magic signature for super vbmeta. */
+#define SUPER_VBMETA_MAGIC 0x5356424d
+
+/* Current super vbmeta version. */
+#define SUPER_VBMETA_MAJOR_VERSION 1
+#define SUPER_VBMETA_MINOR_VERSION 0
+
+/* super vbmeta size. */
+#define SUPER_VBMETA_HEADER_SIZE sizeof(SuperVBMetaHeader)
+#define SUPER_VBMETA_DESCRIPTOR_SIZE sizeof(VBMetaDescriptor)
+#define SUPER_VBMETA_TABLE_MAX_SIZE 2048
+
+/* super vbmeta offset. */
+#define PRIMARY_SUPER_VBMETA_TABLE_OFFSET 0
+#define BACKUP_SUPER_VBMETA_TABLE_OFFSET SUPER_VBMETA_TABLE_MAX_SIZE
+
+/* restriction of vbmeta image */
+#define VBMETA_IMAGE_MAX_NUM 32
+#define VBMETA_IMAGE_MAX_SIZE 64 * 1024
+
+/* Binary format of the super vbmeta image.
+ *
+ * The super vbmeta image consists of two blocks:
+ *
+ *  +------------------------------------------+
+ *  | Super VBMeta Table - fixed size          |
+ *  +------------------------------------------+
+ *  | Backup Super VBMeta Table - fixed size   |
+ *  +------------------------------------------+
+ *  | VBMeta Images - fixed size               |
+ *  +------------------------------------------+
+ *
+ *  The "Super VBMeta Table" records the offset
+ *  and the size of each vbmeta_partition within
+ *  /super_vbmeta.
+ *
+ *  The "VBMeta Image" is copied from each vbmeta_partition
+ *  and filled with 0 until 64K bytes.
+ *
+ * The super vbmeta table consists of two blocks:
+ *
+ *  +-----------------------------------------+
+ *  | Header data - fixed size                |
+ *  +-----------------------------------------+
+ *  | VBMeta descriptors - variable size      |
+ *  +-----------------------------------------+
+ *
+ * The "Header data" block is described by the following struct and
+ * is always 128 bytes long.
+ *
+ * The "VBMeta descriptor" is |descriptors_size| + |vbmeta_name_length|
+ * bytes long. It contains the offset and size for each vbmeta image
+ * and is followed by |vbmeta_name_length| bytes of the partition name
+ * (UTF-8 encoded).
+ */
+
+typedef struct SuperVBMetaHeader {
+    /*  0: Magic signature (SUPER_VBMETA_MAGIC). */
+    uint32_t magic;
+
+    /*  4: Major version. Version number required to read this super vbmeta. If the version is not
+     * equal to the library version, the super vbmeta should be considered incompatible.
+     */
+    uint16_t major_version;
+
+    /*  6: Minor version. A library supporting newer features should be able to
+     * read super vbmeta with an older minor version. However, an older library
+     * should not support reading super vbmeta if its minor version is higher.
+     */
+    uint16_t minor_version;
+
+    /*  8: The size of this header struct. */
+    uint32_t header_size;
+
+    /*  12: The size of this super vbmeta table. */
+    uint32_t total_size;
+
+    /*  16: SHA256 checksum of this super vbmeta table, with this field set to 0. */
+    uint8_t checksum[32];
+
+    /*  48: The size of the vbmeta table descriptors. */
+    uint32_t descriptors_size;
+
+    /*  52: mark which slot is in use. */
+    uint32_t in_use = 0;
+
+    /*  56: reserved for other usage, filled with 0. */
+    uint8_t reserved[72];
+} __attribute__((packed)) SuperVBMetaHeader;
+
+typedef struct VBMetaDescriptor {
+    /*  0: The slot number of the vbmeta image. */
+    uint8_t vbmeta_index;
+
+    /*  12: The length of the vbmeta image name. */
+    uint32_t vbmeta_name_length;
+
+    /*  16: Space reserved for other usage, filled with 0. */
+    uint8_t reserved[48];
+} __attribute__((packed)) VBMetaDescriptor;
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/super_vbmeta_test.cpp b/fs_mgr/libvbmeta/super_vbmeta_test.cpp
new file mode 100644
index 0000000..6b4fc5d
--- /dev/null
+++ b/fs_mgr/libvbmeta/super_vbmeta_test.cpp
@@ -0,0 +1,191 @@
+/*
+ * 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 <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+#include <openssl/sha.h>
+#include <sparse/sparse.h>
+
+#include "reader.h"
+#include "super_vbmeta_format.h"
+#include "utility.h"
+#include "writer.h"
+
+#define FAKE_DATA_SIZE 40960
+#define FAKE_PARTITION_SIZE FAKE_DATA_SIZE * 25
+
+using android::base::Result;
+using android::fs_mgr::GetFileSize;
+using android::fs_mgr::ReadVBMetaImage;
+using SparsePtr = std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)>;
+
+void GeneratePartitionImage(int fd, const std::string& file_name,
+                            const std::string& partition_name) {
+    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(FAKE_DATA_SIZE);
+    for (size_t c = 0; c < FAKE_DATA_SIZE; c++) {
+        buffer[c] = uint8_t(c);
+    }
+
+    SparsePtr file(sparse_file_new(512 /* block size */, FAKE_DATA_SIZE), sparse_file_destroy);
+    EXPECT_TRUE(file);
+    EXPECT_EQ(0, sparse_file_add_data(file.get(), buffer.get(), FAKE_DATA_SIZE,
+                                      0 /* offset in blocks */));
+    EXPECT_EQ(0, sparse_file_write(file.get(), fd, false /* gz */, true /* sparse */,
+                                   false /* crc */));
+
+    std::stringstream cmd;
+    cmd << "avbtool add_hashtree_footer"
+        << " --image " << file_name << " --partition_name " << partition_name
+        << " --partition_size " << FAKE_PARTITION_SIZE << " --algorithm SHA256_RSA2048"
+        << " --key external/avb/test/data/testkey_rsa2048.pem";
+
+    int rc = system(cmd.str().c_str());
+    EXPECT_TRUE(WIFEXITED(rc));
+    EXPECT_EQ(WEXITSTATUS(rc), 0);
+}
+
+void GenerateVBMetaImage(const std::string& vbmeta_file_name,
+                         const std::string& include_file_name) {
+    std::stringstream cmd;
+    cmd << "avbtool make_vbmeta_image"
+        << " --output " << vbmeta_file_name << " --include_descriptors_from_image "
+        << include_file_name;
+
+    int rc = system(cmd.str().c_str());
+    EXPECT_TRUE(WIFEXITED(rc));
+    EXPECT_EQ(WEXITSTATUS(rc), 0);
+}
+
+std::string ReadVBMetaImageFromFile(const std::string& file) {
+    android::base::unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
+    EXPECT_GT(fd, 0);
+    Result<uint64_t> file_size = GetFileSize(fd);
+    EXPECT_TRUE(file_size);
+    std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(VBMETA_IMAGE_MAX_SIZE);
+    EXPECT_TRUE(android::base::ReadFully(fd, buffer.get(), file_size.value()));
+    return std::string(reinterpret_cast<char*>(buffer.get()), VBMETA_IMAGE_MAX_SIZE);
+}
+
+TEST(VBMetaTableTest, VBMetaTableBasic) {
+    TemporaryDir td;
+
+    // Generate Partition Image
+    TemporaryFile system_tf(std::string(td.path));
+    std::string system_path(system_tf.path);
+    GeneratePartitionImage(system_tf.fd, system_path, "system");
+    system_tf.release();
+
+    TemporaryFile vendor_tf(std::string(td.path));
+    std::string vendor_path(vendor_tf.path);
+    GeneratePartitionImage(vendor_tf.fd, vendor_path, "vendor");
+    vendor_tf.release();
+
+    TemporaryFile product_tf(std::string(td.path));
+    std::string product_path(product_tf.path);
+    GeneratePartitionImage(product_tf.fd, product_path, "product");
+    product_tf.release();
+
+    // Generate VBMeta Image
+    std::string vbmeta_system_path(td.path);
+    vbmeta_system_path.append("/vbmeta_system.img");
+    GenerateVBMetaImage(vbmeta_system_path, system_path);
+
+    std::string vbmeta_vendor_path(td.path);
+    vbmeta_vendor_path.append("/vbmeta_vendor.img");
+    GenerateVBMetaImage(vbmeta_vendor_path, vendor_path);
+
+    std::string vbmeta_product_path(td.path);
+    vbmeta_product_path.append("/vbmeta_product.img");
+    GenerateVBMetaImage(vbmeta_product_path, product_path);
+
+    // Generate Super VBMeta Image
+    std::string super_vbmeta_path(td.path);
+    super_vbmeta_path.append("/super_vbmeta.img");
+
+    std::stringstream cmd;
+    cmd << "vbmake"
+        << " --image "
+        << "vbmeta_system"
+        << "=" << vbmeta_system_path << " --image "
+        << "vbmeta_vendor"
+        << "=" << vbmeta_vendor_path << " --image "
+        << "vbmeta_product"
+        << "=" << vbmeta_product_path << " --output=" << super_vbmeta_path;
+
+    int rc = system(cmd.str().c_str());
+    ASSERT_TRUE(WIFEXITED(rc));
+    ASSERT_EQ(WEXITSTATUS(rc), 0);
+
+    android::base::unique_fd fd(open(super_vbmeta_path.c_str(), O_RDONLY | O_CLOEXEC));
+    EXPECT_GT(fd, 0);
+
+    // Check the size of vbmeta table
+    Result<uint64_t> super_vbmeta_size = GetFileSize(fd);
+    EXPECT_TRUE(super_vbmeta_size);
+    EXPECT_EQ(super_vbmeta_size.value(),
+              SUPER_VBMETA_TABLE_MAX_SIZE * 2 + VBMETA_IMAGE_MAX_SIZE * 3);
+
+    // Check Primary vbmeta table is equal to Backup one
+    VBMetaTable table;
+    EXPECT_TRUE(android::fs_mgr::ReadPrimaryVBMetaTable(fd, &table));
+    VBMetaTable table_backup;
+    EXPECT_TRUE(android::fs_mgr::ReadBackupVBMetaTable(fd, &table_backup));
+    EXPECT_EQ(android::fs_mgr::SerializeVBMetaTable(table),
+              android::fs_mgr::SerializeVBMetaTable(table_backup));
+
+    // Check vbmeta table Header Checksum
+    std::string serial_table = android::fs_mgr::SerializeVBMetaTable(table);
+    std::string serial_removed_checksum(serial_table);
+    // Replace checksum 32 bytes (starts at 16th byte) with 0
+    serial_removed_checksum.replace(16, 32, 32, 0);
+    uint8_t test_checksum[32];
+    ::SHA256(reinterpret_cast<const uint8_t*>(serial_removed_checksum.c_str()),
+             table.header.total_size, &test_checksum[0]);
+    EXPECT_EQ(memcmp(table.header.checksum, test_checksum, 32), 0);
+
+    // Check vbmeta table descriptors and vbmeta images
+    EXPECT_EQ(table.descriptors.size(), 3);
+
+    EXPECT_EQ(table.descriptors[0].vbmeta_index, 0);
+    EXPECT_EQ(table.descriptors[0].vbmeta_name_length, 14);
+    EXPECT_EQ(table.descriptors[0].vbmeta_name, "vbmeta_product");
+    Result<std::string> vbmeta_product_content = ReadVBMetaImage(fd, 0);
+    EXPECT_TRUE(vbmeta_product_content);
+    EXPECT_EQ(ReadVBMetaImageFromFile(vbmeta_product_path), vbmeta_product_content.value());
+
+    EXPECT_EQ(table.descriptors[1].vbmeta_index, 1);
+    EXPECT_EQ(table.descriptors[1].vbmeta_name_length, 13);
+    EXPECT_EQ(table.descriptors[1].vbmeta_name, "vbmeta_system");
+    Result<std::string> vbmeta_system_content = ReadVBMetaImage(fd, 1);
+    EXPECT_TRUE(vbmeta_system_content);
+    EXPECT_EQ(ReadVBMetaImageFromFile(vbmeta_system_path), vbmeta_system_content.value());
+
+    EXPECT_EQ(table.descriptors[2].vbmeta_index, 2);
+    EXPECT_EQ(table.descriptors[2].vbmeta_name_length, 13);
+    EXPECT_EQ(table.descriptors[2].vbmeta_name, "vbmeta_vendor");
+    Result<std::string> vbmeta_vendor_content = ReadVBMetaImage(fd, 2);
+    EXPECT_TRUE(vbmeta_vendor_content);
+    EXPECT_EQ(ReadVBMetaImageFromFile(vbmeta_vendor_path), vbmeta_vendor_content.value());
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/utility.cpp b/fs_mgr/libvbmeta/utility.cpp
new file mode 100644
index 0000000..c184227
--- /dev/null
+++ b/fs_mgr/libvbmeta/utility.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "utility.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "super_vbmeta_format.h"
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+namespace fs_mgr {
+
+Result<uint64_t> GetFileSize(int fd) {
+    struct stat sb;
+    if (fstat(fd, &sb) == -1) {
+        return ErrnoError() << "Couldn't get the file size";
+    }
+    return sb.st_size;
+}
+
+uint64_t IndexOffset(const uint8_t vbmeta_index) {
+    /* There are primary and backup vbmeta table in super_vbmeta,
+       so SUPER_VBMETA_TABLE_MAX_SIZE is counted twice. */
+    return 2 * SUPER_VBMETA_TABLE_MAX_SIZE + vbmeta_index * VBMETA_IMAGE_MAX_SIZE;
+}
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/libfiemap_writer/utility.h b/fs_mgr/libvbmeta/utility.h
similarity index 60%
copy from fs_mgr/libfiemap_writer/utility.h
copy to fs_mgr/libvbmeta/utility.h
index 2d418da..91db0ad 100644
--- a/fs_mgr/libfiemap_writer/utility.h
+++ b/fs_mgr/libvbmeta/utility.h
@@ -16,15 +16,22 @@
 
 #pragma once
 
-#include <string>
+#include <android-base/logging.h>
+#include <android-base/result.h>
+
+#define VBMETA_TAG "[libvbmeta]"
+#define LWARN LOG(WARNING) << VBMETA_TAG
+#define LINFO LOG(INFO) << VBMETA_TAG
+#define LERROR LOG(ERROR) << VBMETA_TAG
+#define PWARNING PLOG(WARNING) << VBMETA_TAG
+#define PERROR PLOG(ERROR) << VBMETA_TAG
 
 namespace android {
-namespace fiemap_writer {
+namespace fs_mgr {
 
-// Given a file that will be created, determine the maximum size its containing
-// filesystem allows. Note this is a theoretical maximum size; free space is
-// ignored entirely.
-uint64_t DetermineMaximumFileSize(const std::string& file_path);
+android::base::Result<uint64_t> GetFileSize(int fd);
 
-}  // namespace fiemap_writer
-}  // namespace android
+uint64_t IndexOffset(const uint8_t vbmeta_index);
+
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/writer.cpp b/fs_mgr/libvbmeta/writer.cpp
new file mode 100644
index 0000000..fc0e0fb
--- /dev/null
+++ b/fs_mgr/libvbmeta/writer.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 "writer.h"
+
+#include <android-base/file.h>
+
+#include "utility.h"
+
+using android::base::ErrnoError;
+using android::base::Result;
+
+namespace android {
+namespace fs_mgr {
+
+std::string SerializeVBMetaTable(const VBMetaTable& input) {
+    std::string table;
+    table.append(reinterpret_cast<const char*>(&input.header), SUPER_VBMETA_HEADER_SIZE);
+
+    for (const auto& desc : input.descriptors) {
+        table.append(reinterpret_cast<const char*>(&desc), SUPER_VBMETA_DESCRIPTOR_SIZE);
+        table.append(desc.vbmeta_name);
+    }
+
+    // Ensure the size of vbmeta table is SUPER_VBMETA_TABLE_MAX_SIZE
+    table.resize(SUPER_VBMETA_TABLE_MAX_SIZE, '\0');
+
+    return table;
+}
+
+Result<void> WritePrimaryVBMetaTable(int fd, const std::string& table) {
+    const uint64_t offset = PRIMARY_SUPER_VBMETA_TABLE_OFFSET;
+    if (lseek(fd, offset, SEEK_SET) < 0) {
+        return ErrnoError() << __PRETTY_FUNCTION__ << " lseek failed";
+    }
+
+    if (!android::base::WriteFully(fd, table.data(), table.size())) {
+        return ErrnoError() << "Failed to write primary vbmeta table at offset " << offset;
+    }
+    return {};
+}
+
+Result<void> WriteBackupVBMetaTable(int fd, const std::string& table) {
+    const uint64_t offset = BACKUP_SUPER_VBMETA_TABLE_OFFSET;
+    if (lseek(fd, offset, SEEK_SET) < 0) {
+        return ErrnoError() << __PRETTY_FUNCTION__ << " lseek failed";
+    }
+
+    if (!android::base::WriteFully(fd, table.data(), table.size())) {
+        return ErrnoError() << "Failed to write backup vbmeta table at offset " << offset;
+    }
+    return {};
+}
+
+Result<void> WriteVBMetaImage(int fd, const uint8_t slot_number, const std::string& vbmeta_image) {
+    const uint64_t offset = IndexOffset(slot_number);
+    if (lseek(fd, offset, SEEK_SET) < 0) {
+        return ErrnoError() << __PRETTY_FUNCTION__ << " lseek failed";
+    }
+
+    if (!android::base::WriteFully(fd, vbmeta_image.data(), vbmeta_image.size())) {
+        return ErrnoError() << "Failed to write vbmeta image at offset " << offset;
+    }
+    return {};
+}
+
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libvbmeta/writer.h b/fs_mgr/libvbmeta/writer.h
new file mode 100644
index 0000000..f8eed36
--- /dev/null
+++ b/fs_mgr/libvbmeta/writer.h
@@ -0,0 +1,36 @@
+/*
+ * 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 <string>
+
+#include <android-base/result.h>
+
+#include "super_vbmeta_format.h"
+
+namespace android {
+namespace fs_mgr {
+
+std::string SerializeVBMetaTable(const VBMetaTable& input);
+
+android::base::Result<void> WritePrimaryVBMetaTable(int fd, const std::string& table);
+android::base::Result<void> WriteBackupVBMetaTable(int fd, const std::string& table);
+android::base::Result<void> WriteVBMetaImage(int fd, const uint8_t slot_number,
+                                             const std::string& vbmeta_image);
+
+}  // namespace fs_mgr
+}  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp
index eb9f525..4f6ec5a 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -13,8 +13,21 @@
 // limitations under the License.
 
 cc_test {
-    name: "fs_mgr_unit_test",
-    test_suites: ["device-tests"],
+    name: "CtsFsMgrTestCases",
+    test_suites: [
+        "cts",
+        "device-tests",
+        "vts",
+    ],
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
 
     shared_libs: [
         "libbase",
@@ -25,6 +38,7 @@
         "libfstab",
     ],
     srcs: [
+        "file_wait_test.cpp",
         "fs_mgr_test.cpp",
     ],
 
diff --git a/fs_mgr/tests/AndroidTest.xml b/fs_mgr/tests/AndroidTest.xml
new file mode 100644
index 0000000..91c3fb9
--- /dev/null
+++ b/fs_mgr/tests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for CTS fs_mgr 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="CtsFsMgrTestCases->/data/local/tmp/CtsFsMgrTestCases" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="CtsFsMgrTestCases" />
+        <option name="runtime-hint" value="65s" />
+    </test>
+</configuration>
diff --git a/fs_mgr/tests/adb-remount-sh.xml b/fs_mgr/tests/adb-remount-sh.xml
index 716e324..fa0d63f 100644
--- a/fs_mgr/tests/adb-remount-sh.xml
+++ b/fs_mgr/tests/adb-remount-sh.xml
@@ -18,6 +18,8 @@
     <!-- This test requires a device, so it's not annotated with a null-device -->
     <test class="com.android.tradefed.testtype.binary.ExecutableHostTest" >
         <option name="binary" value="adb-remount-test.sh" />
+        <!-- Increase default timeout as script is quite long -->
+        <option name="per-binary-timeout" value="1h" />
     </test>
 </configuration>
 
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index c22176b..4226e95 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -15,10 +15,13 @@
 
 adb remount tests
 
---help        This help
---serial      Specify device (must if multiple are present)
---color       Dress output with highlighting colors
---print-time  Report the test duration
+--color                     Dress output with highlighting colors
+--help                      This help
+--no-wait-screen            Do not wait for display screen to settle
+--print-time                Report the test duration
+--serial                    Specify device (must if multiple are present)
+--wait-adb <duration>       adb wait timeout
+--wait-fastboot <duration>  fastboot wait timeout
 
 Conditions:
  - Must be a userdebug build.
@@ -33,7 +36,10 @@
 ##  Helper Variables
 ##
 
+EMPTY=""
 SPACE=" "
+# Line up wrap to [  XXXXXXX ] messages.
+INDENT="             "
 # A _real_ embedded tab character
 TAB="`echo | tr '\n' '\t'`"
 # A _real_ embedded escape character
@@ -50,6 +56,10 @@
 start_time=`date +%s`
 ACTIVE_SLOT=
 
+ADB_WAIT=4m
+FASTBOOT_WAIT=2m
+screen_wait=true
+
 ##
 ##  Helper Functions
 ##
@@ -131,10 +141,29 @@
 adb_logcat() {
   echo "${RED}[     INFO ]${NORMAL} logcat ${@}" >&2 &&
   adb logcat "${@}" </dev/null |
+    tr -d '\r' |
     grep -v 'logd    : logdr: UID=' |
     sed -e '${/------- beginning of kernel/d}' -e 's/^[0-1][0-9]-[0-3][0-9] //'
 }
 
+[ "USAGE: avc_check >/dev/stderr
+
+Returns: worrisome avc violations" ]
+avc_check() {
+  if ! ${overlayfs_supported:-false}; then
+    return
+  fi
+  local L=`adb_logcat -b all -v brief -d \
+                      -e 'context=u:object_r:unlabeled:s0' 2>/dev/null |
+             sed -n 's/.*avc: //p' |
+             sort -u`
+  if [ -z "${L}" ]; then
+    return
+  fi
+  echo "${ORANGE}[  WARNING ]${NORMAL} unlabeled sepolicy violations:" >&2
+  echo "${L}" | sed "s/^/${INDENT}/" >&2
+}
+
 [ "USAGE: get_property <prop>
 
 Returns the property value" ]
@@ -161,7 +190,7 @@
 [ "USAGE: adb_cat <file> >stdout
 
 Returns: content of file to stdout with carriage returns skipped,
-         true of the file exists" ]
+         true if the file exists" ]
 adb_cat() {
     local OUTPUT="`adb_sh cat ${1} </dev/null 2>&1`"
     local ret=${?}
@@ -169,11 +198,23 @@
     return ${ret}
 }
 
+[ "USAGE: adb_ls <dirfile> >stdout
+
+Returns: filename or directoru content to stdout with carriage returns skipped,
+         true if the ls had no errors" ]
+adb_ls() {
+    local OUTPUT="`adb_sh ls ${1} </dev/null 2>/dev/null`"
+    local ret=${?}
+    echo "${OUTPUT}" | tr -d '\r'
+    return ${ret}
+}
+
 [ "USAGE: adb_reboot
 
 Returns: true if the reboot command succeeded" ]
 adb_reboot() {
-  adb reboot remount-test || true
+  avc_check
+  adb reboot remount-test </dev/null || true
   sleep 2
 }
 
@@ -219,13 +260,34 @@
   echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10`
 }
 
+[ "USAGE: USB_DEVICE=\`usb_devnum [--next]\`
+
+USB_DEVICE contains cache. Update if system changes.
+
+Returns: the devnum for the USB_SERIAL device" ]
+usb_devnum() {
+  if [ -n "${USB_SERIAL}" ]; then
+    local usb_device=`cat ${USB_SERIAL%/serial}/devnum 2>/dev/null | tr -d ' \t\r\n'`
+    if [ -n "${usb_device}" ]; then
+      USB_DEVICE=dev${usb_device}
+    elif [ -n "${USB_DEVICE}" -a "${1}" ]; then
+      USB_DEVICE=dev`expr ${USB_DEVICE#dev} + 1`
+    fi
+    echo "${USB_DEVICE}"
+  fi
+}
+
 [ "USAGE: adb_wait [timeout]
 
 Returns: waits until the device has returned for adb or optional timeout" ]
 adb_wait() {
+  local start=`date +%s`
+  local duration=
   local ret
   if [ -n "${1}" ]; then
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    USB_DEVICE=`usb_devnum --next`
+    duration=`format_duration ${1}`
+    echo -n ". . . waiting ${duration}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -233,30 +295,83 @@
     adb wait-for-device
     ret=${?}
   fi
+  USB_DEVICE=`usb_devnum`
   if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
     local active_slot=`get_active_slot`
     if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
       echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
     fi
   fi
+  local end=`date +%s`
+  local diff_time=`expr ${end} - ${start}`
+  local _print_time=${print_time}
+  if [ ${diff_time} -lt 15 ]; then
+    _print_time=false
+  fi
+  diff_time=`format_duration ${diff_time}`
+  if [ "${diff_time}" = "${duration}" ]; then
+    _print_time=false
+  fi
+
+  local reason=
+  if inAdb; then
+    reason=`get_property ro.boot.bootreason`
+  fi
+  case ${reason} in
+    reboot*)
+      reason=
+      ;;
+    ${EMPTY})
+      ;;
+    *)
+      reason=" for boot reason ${reason}"
+      ;;
+  esac
+  if ${_print_time} || [ -n "${reason}" ]; then
+    echo "${BLUE}[     INFO ]${NORMAL} adb wait duration ${diff_time}${reason}"
+  fi >&2
+
   return ${ret}
 }
 
-[ "USAGE: usb_status > stdout
+[ "USAGE: adb_user > /dev/stdout
 
-If adb_wait failed, check if device is in adb, recovery or fastboot mode
-and report status string.
+Returns: the adb daemon user" ]
+adb_user() {
+  adb_sh echo '${USER}' </dev/null
+}
 
-Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ]
+[ "USAGE: usb_status > stdout 2> stderr
+
+Assumes referenced right after adb_wait or fastboot_wait failued.
+If wait failed, check if device is in adb, recovery or fastboot mode
+and report status strings like  \"(USB stack borken?)\",
+\"(In fastboot mode)\", \"(In recovery mode)\" or \"(in adb mode)\".
+Additional diagnostics may be provided to the stderr output.
+
+Returns: USB status string" ]
 usb_status() {
   if inFastboot; then
     echo "(In fastboot mode)"
   elif inRecovery; then
     echo "(In recovery mode)"
   elif inAdb; then
-    echo "(In adb mode)"
+    echo "(In adb mode `adb_user`)"
   else
-    echo "(USB stack borken?)"
+    echo "(USB stack borken for ${USB_ADDRESS})"
+    USB_DEVICE=`usb_devnum`
+    if [ -n "${USB_DEVICE}" ]; then
+      echo "# lsusb -v -s ${USB_DEVICE#dev}"
+      local D=`lsusb -v -s ${USB_DEVICE#dev} 2>&1`
+      if [ -n "${D}" ]; then
+        echo "${D}"
+      else
+        lsusb -v
+      fi
+    else
+      echo "# lsusb -v (expected device missing)"
+      lsusb -v
+    fi >&2
   fi
 }
 
@@ -268,7 +383,8 @@
   # fastboot has no wait-for-device, but it does an automatic
   # wait and requires (even a nonsensical) command to do so.
   if [ -n "${1}" ]; then
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    USB_DEVICE=`usb_devnum --next`
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -278,11 +394,12 @@
   fi ||
     inFastboot
   ret=${?}
+  USB_DEVICE=`usb_devnum`
   if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
     local active_slot=`get_active_slot`
     if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
-      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
-    fi
+      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+    fi >&2
   fi
   return ${ret}
 }
@@ -293,7 +410,8 @@
 recovery_wait() {
   local ret
   if [ -n "${1}" ]; then
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    USB_DEVICE=`usb_devnum --next`
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -301,11 +419,12 @@
     adb wait-for-recovery
     ret=${?}
   fi
+  USB_DEVICE=`usb_devnum`
   if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
     local active_slot=`get_active_slot`
     if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
-      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
-    fi
+      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+    fi >&2
   fi
   return ${ret}
 }
@@ -327,17 +446,72 @@
   inFastboot || inAdb || inRecovery
 }
 
+wait_for_screen_timeout=900
+[ "USAGE: wait_for_screen [-n] [TIMEOUT]
+
+-n - echo newline at exit
+TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ]
+wait_for_screen() {
+  if ! ${screen_wait}; then
+    adb_wait
+    return
+  fi
+  exit_function=true
+  if [ X"-n" = X"${1}" ]; then
+    exit_function=echo
+    shift
+  fi
+  timeout=${wait_for_screen_timeout}
+  if [ ${#} -gt 0 ]; then
+    timeout=${1}
+    shift
+  fi
+  counter=0
+  while true; do
+    if inFastboot; then
+      fastboot reboot
+    elif inAdb; then
+      if [ 0 != ${counter} ]; then
+        adb_wait
+      fi
+      if [ -n "`get_property sys.boot.reason`" ]
+      then
+        vals=`get_property |
+              sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
+        if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]
+        then
+          sleep 1
+          break
+        fi
+        if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]
+        then
+          sleep 1
+          break
+        fi
+      fi
+    fi
+    counter=`expr ${counter} + 1`
+    if [ ${counter} -gt ${timeout} ]; then
+      ${exit_function}
+      echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
+      return 1
+    fi
+    sleep 1
+  done
+  ${exit_function}
+}
+
 [ "USAGE: adb_root
 
 NB: This can be flakey on devices due to USB state
 
 Returns: true if device in root state" ]
 adb_root() {
-  [ root != "`adb_sh echo '${USER}' </dev/null`" ] || return 0
+  [ root != "`adb_user`" ] || return 0
   adb root >/dev/null </dev/null 2>/dev/null
   sleep 2
-  adb_wait 2m &&
-    [ root = "`adb_sh echo '${USER}' </dev/null`" ]
+  adb_wait ${ADB_WAIT} &&
+    [ root = "`adb_user`" ]
 }
 
 [ "USAGE: adb_unroot
@@ -346,11 +520,11 @@
 
 Returns: true if device in un root state" ]
 adb_unroot() {
-  [ root = "`adb_sh echo '${USER}' </dev/null`" ] || return 0
+  [ root = "`adb_user`" ] || return 0
   adb unroot >/dev/null </dev/null 2>/dev/null
   sleep 2
-  adb_wait 2m &&
-    [ root != "`adb_sh echo '${USER}' </dev/null`" ]
+  adb_wait ${ADB_WAIT} &&
+    [ root != "`adb_user`" ]
 }
 
 [ "USAGE: fastboot_getvar var expected >/dev/stderr
@@ -370,10 +544,10 @@
     O="${1}: <empty>"
   fi
   if [ -n "${2}" -a "${1}: ${2}" != "${O}" ]; then
-    echo "${2} != ${O}" >&2
+    echo "${2} != ${O}"
     false
     return
-  fi
+  fi >&2
   echo ${O} >&2
 }
 
@@ -430,16 +604,16 @@
 Returns: exit failure, report status" ]
 die() {
   if [ X"-d" = X"${1}" ]; then
-    adb_logcat -b all -v nsec -d >&2
+    adb_logcat -b all -v nsec -d
     shift
   elif [ X"-t" = X"${1}" ]; then
     if [ -n "${2}" ]; then
-      adb_logcat -b all -v nsec -t ${2} >&2
+      adb_logcat -b all -v nsec -t ${2}
     else
-      adb_logcat -b all -v nsec -d >&2
+      adb_logcat -b all -v nsec -d
     fi
     shift 2
-  fi
+  fi >&2
   echo "${RED}[  FAILED  ]${NORMAL} ${@}" >&2
   cleanup
   restore
@@ -464,39 +638,63 @@
   if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then
     if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval%
 *}" ]; then
-      echo "${prefix} expected \"${lval}\"" >&2
+      echo "${prefix} expected \"${lval}\""
       echo "${prefix} got \"${rval}\"" |
-        sed ': again
+        sed ": again
              N
-             s/\(\n\)\([^ ]\)/\1             \2/
-             t again' >&2
+             s/\(\n\)\([^ ]\)/\1${INDENT}\2/
+             t again"
       if [ -n "${*}" ] ; then
-        echo "${prefix} ${*}" >&2
+        echo "${prefix} ${*}"
       fi
     else
-      echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}" >&2
-    fi
+      echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}"
+    fi >&2
     return ${error}
   fi
   if [ -n "${*}" ] ; then
     prefix="${GREEN}[     INFO ]${NORMAL}"
     if [ X"${lval}" != X"${rval}" ]; then  # we were supplied a regex?
       if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval% *}" ]; then
-        echo "${prefix} ok \"${lval}\"" >&2
+        echo "${prefix} ok \"${lval}\""
         echo "       = \"${rval}\"" |
-          sed ': again
+          sed ": again
                N
-               s/\(\n\)\([^ ]\)/\1          \2/
-               t again' >&2
+               s/\(\n\)\([^ ]\)/\1${INDENT}\2/
+               t again"
         if [ -n "${*}" ] ; then
-          echo "${prefix} ${*}" >&2
+          echo "${prefix} ${*}"
         fi
       else
-        echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}" >&2
+        echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}"
       fi
     else
-      echo "${prefix} ok \"${lval}\" ${*}" >&2
-    fi
+      echo "${prefix} ok \"${lval}\" ${*}"
+    fi >&2
+  fi
+  return 0
+}
+
+[ "USAGE: EXPECT_NE <lval> <rval> [--warning [message]]
+
+Returns true if lval matches rval" ]
+EXPECT_NE() {
+  local lval="${1}"
+  local rval="${2}"
+  shift 2
+  local error=1
+  local prefix="${RED}[    ERROR ]${NORMAL}"
+  if [ X"${1}" = X"--warning" ]; then
+      prefix="${RED}[  WARNING ]${NORMAL}"
+      error=0
+      shift 1
+  fi
+  if [ X"${rval}" = X"${lval}" ]; then
+    echo "${prefix} did not expect \"${lval}\" ${*}" >&2
+    return ${error}
+  fi
+  if [ -n "${*}" ] ; then
+    echo "${prefix} ok \"${lval}\" not \"${rval}\" ${*}" >&2
   fi
   return 0
 }
@@ -512,8 +710,25 @@
       EXPECT_EQ "${lval}" "${rval}" ${*}
       return
   fi
-  EXPECT_EQ "${lval}" "${rval}" ||
+  if ! EXPECT_EQ "${lval}" "${rval}"; then
     die "${@}"
+  fi
+}
+
+[ "USAGE: check_ne <lval> <rval> [--warning [message]]
+
+Exits if lval matches rval" ]
+check_ne() {
+  local lval="${1}"
+  local rval="${2}"
+  shift 2
+  if [ X"${1}" = X"--warning" ]; then
+      EXPECT_NE "${lval}" "${rval}" ${*}
+      return
+  fi
+  if ! EXPECT_NE "${lval}" "${rval}"; then
+    die "${@}"
+  fi
 }
 
 [ "USAGE: skip_administrative_mounts [data] < /proc/mounts
@@ -550,6 +765,9 @@
 
 OPTIONS=`getopt --alternative --unquoted \
                 --longoptions help,serial:,colour,color,no-colour,no-color \
+                --longoptions wait-adb:,wait-fastboot: \
+                --longoptions wait-screen,wait-display \
+                --longoptions no-wait-screen,no-wait-display \
                 --longoptions gtest_print_time,print-time \
                 -- "?hs:" ${*}` ||
   ( echo "${USAGE}" >&2 ; false ) ||
@@ -573,9 +791,23 @@
     --no-color | --no-colour)
       color=false
       ;;
+    --no-wait-display | --no-wait-screen)
+      screen_wait=false
+      ;;
+    --wait-display | --wait-screen)
+      screen_wait=true
+      ;;
     --print-time | --gtest_print_time)
       print_time=true
       ;;
+    --wait-adb)
+      ADB_WAIT=${2}
+      shift
+      ;;
+    --wait-fastboot)
+      FASTBOOT_WAIT=${2}
+      shift
+      ;;
     --)
       shift
       break
@@ -606,7 +838,7 @@
 inRecovery && die "device in recovery mode"
 if ! inAdb; then
   echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode" >&2
-  adb_wait 2m
+  adb_wait ${ADB_WAIT}
 fi
 inAdb || die "specified device not in adb mode"
 isDebuggable || die "device not a debug build"
@@ -618,6 +850,8 @@
 
 # Do something.
 
+# Collect characteristics of the device and report.
+
 D=`get_property ro.serialno`
 [ -n "${D}" ] || D=`get_property ro.boot.serialno`
 [ -z "${D}" -o -n "${ANDROID_SERIAL}" ] || ANDROID_SERIAL=${D}
@@ -631,7 +865,8 @@
   USB_ADDRESS=usb${USB_ADDRESS##*/}
 fi
 [ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] ||
-  echo "${BLUE}[     INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} >&2
+  USB_DEVICE=`usb_devnum`
+  echo "${BLUE}[     INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} >&2
 BUILD_DESCRIPTION=`get_property ro.build.description`
 [ -z "${BUILD_DESCRIPTION}" ] ||
   echo "${BLUE}[     INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
@@ -639,49 +874,106 @@
 [ -z "${ACTIVE_SLOT}" ] ||
   echo "${BLUE}[     INFO ]${NORMAL} active slot is ${ACTIVE_SLOT}" >&2
 
+# Acquire list of system partitions
+
+PARTITIONS=`adb_su cat /vendor/etc/fstab* |
+              skip_administrative_mounts |
+              sed -n "s@^\([^ ${TAB}/][^ ${TAB}/]*\)[ ${TAB}].*[, ${TAB}]ro[, ${TAB}].*@\1@p" |
+              sort -u |
+              tr '\n' ' '`
+PARTITIONS="${PARTITIONS:-system vendor}"
+# KISS (we do not support sub-mounts for system partitions currently)
+MOUNTS="`for i in ${PARTITIONS}; do
+           echo /${i}
+         done |
+         tr '\n' ' '`"
+echo "${BLUE}[     INFO ]${NORMAL} System Partitions list: ${PARTITIONS}" >&2
+
 # Report existing partition sizes
-adb_sh ls -l /dev/block/by-name/ </dev/null 2>/dev/null |
+adb_sh ls -l /dev/block/by-name/ /dev/block/mapper/ </dev/null 2>/dev/null |
   sed -n 's@.* \([^ ]*\) -> /dev/block/\([^ ]*\)$@\1 \2@p' |
   while read name device; do
-    case ${name} in
-      system_[ab] | system | vendor_[ab] | vendor | super | cache)
-        case ${device} in
-          sd*)
-            device=${device%%[0-9]*}/${device}
-            ;;
-        esac
-        size=`adb_su cat /sys/block/${device}/size 2>/dev/null </dev/null` &&
-          size=`expr ${size} / 2` &&
-          echo "${BLUE}[     INFO ]${NORMAL} partition ${name} device ${device} size ${size}K" >&2
+    [ super = ${name} -o cache = ${name} ] ||
+      (
+        for i in ${PARTITIONS}; do
+          [ ${i} = ${name} -o ${i} = ${name%_[ab]} ] && exit
+        done
+        exit 1
+      ) ||
+      continue
+
+    case ${device} in
+      sd*)
+        device=${device%%[0-9]*}/${device}
         ;;
     esac
+    size=`adb_su cat /sys/block/${device}/size 2>/dev/null </dev/null` &&
+      size=`expr ${size} / 2` &&
+      echo "${BLUE}[     INFO ]${NORMAL} partition ${name} device ${device} size ${size}K" >&2
   done
 
+# If reboot too soon after fresh flash, could trip device update failure logic
+wait_for_screen
 # Can we test remount -R command?
+OVERLAYFS_BACKING="cache mnt/scratch"
 overlayfs_supported=true
-if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
-     "2" = "`get_property partition.system.verified`" ]; then
+if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
+     "2" != "`get_property partition.system.verified`" ]; then
   restore() {
     ${overlayfs_supported} || return 0
     inFastboot &&
       fastboot reboot &&
-      adb_wait 2m
+      adb_wait ${ADB_WAIT} ||
+      true
+    if inAdb; then
+      reboot=false
+      for d in ${OVERLAYFS_BACKING}; do
+        if adb_su ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
+          adb_su rm -rf /${d}/overlay </dev/null
+          reboot=true
+        fi
+      done
+      if ${reboot}; then
+        adb_reboot &&
+        adb_wait ${ADB_WAIT}
+      fi
+    fi
+  }
+else
+  restore() {
+    ${overlayfs_supported} || return 0
+    inFastboot &&
+      fastboot reboot &&
+      adb_wait ${ADB_WAIT} ||
+      true
     inAdb &&
       adb_root &&
       adb enable-verity >/dev/null 2>/dev/null &&
       adb_reboot &&
-      adb_wait 2m
+      adb_wait ${ADB_WAIT}
   }
 
   echo "${GREEN}[ RUN      ]${NORMAL} Testing adb shell su root remount -R command" >&2
 
-  adb_su remount -R system </dev/null || true
+  avc_check
+  T=`adb_date`
+  adb_su remount -R system </dev/null
+  err=${?}
+  if [ "${err}" != 0 ]; then
+    echo "${ORANGE}[  WARNING ]${NORMAL} adb shell su root remount -R system = ${err}, likely did not reboot!" >&2
+    T="-t ${T}"
+  else
+    # Rebooted, logcat will be meaningless, and last logcat will likely be clear
+    T=""
+  fi
   sleep 2
-  adb_wait 2m ||
-    die "waiting for device after remount -R `usb_status`"
+  adb_wait ${ADB_WAIT} ||
+    die "waiting for device after adb shell su root remount -R system `usb_status`"
   if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
        "2" = "`get_property partition.system.verified`" ]; then
-    die "remount -R command failed"
+    die ${T} "remount -R command failed
+${INDENT}ro.boot.verifiedbootstate=\"`get_property ro.boot.verifiedbootstate`\"
+${INDENT}partition.system.verified=\"`get_property partition.system.verified`\""
   fi
 
   echo "${GREEN}[       OK ]${NORMAL} adb shell su root remount -R command" >&2
@@ -723,7 +1015,6 @@
 # So lets do our best to surgically wipe the overlayfs state without
 # having to go through enable-verity transition.
 reboot=false
-OVERLAYFS_BACKING="cache mnt/scratch"
 for d in ${OVERLAYFS_BACKING}; do
   if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
     echo "${ORANGE}[  WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2
@@ -735,7 +1026,7 @@
 if ${reboot}; then
   echo "${ORANGE}[  WARNING ]${NORMAL} rebooting before test" >&2
   adb_reboot &&
-    adb_wait 2m ||
+    adb_wait ${ADB_WAIT} ||
     die "lost device after reboot after wipe `usb_status`"
   adb_root ||
     die "lost device after elevation to root after wipe `usb_status`"
@@ -766,6 +1057,15 @@
 echo "${D}"
 if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then
   overlayfs_needed=false
+  # if device does not need overlays, then adb enable-verity will brick device
+  restore() {
+    ${overlayfs_supported} || return 0
+    inFastboot &&
+      fastboot reboot &&
+      adb_wait ${ADB_WAIT}
+    inAdb &&
+      adb_wait ${ADB_WAIT}
+  }
 elif ! ${overlayfs_supported}; then
   die "need overlayfs, but do not have it"
 fi
@@ -800,7 +1100,7 @@
   echo "${GREEN}[     INFO ]${NORMAL} rebooting as requested" >&2
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
-    adb_wait 2m ||
+    adb_wait ${ADB_WAIT} ||
     die "lost device after reboot requested `usb_status`"
   adb_root ||
     die "lost device after elevation to root `usb_status`"
@@ -841,6 +1141,11 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} remount" >&2
 
+# Feed log with selinux denials as baseline before overlays
+adb_unroot
+adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null
+adb_root
+
 D=`adb remount 2>&1`
 ret=${?}
 echo "${D}"
@@ -897,6 +1202,11 @@
     skip_unrelated_mounts |
     grep " overlay ro,") ||
     die "remount overlayfs missed a spot (ro)"
+  !(adb_sh grep -v noatime /proc/mounts </dev/null |
+    skip_administrative_mounts data |
+    skip_unrelated_mounts |
+    grep -v ' ro,') ||
+    die "mounts are not noatime"
   D=`adb_sh grep " rw," /proc/mounts </dev/null |
      skip_administrative_mounts data`
   if echo "${D}" | grep /dev/root >/dev/null; then
@@ -930,17 +1240,39 @@
 
 # Check something.
 
-echo "${GREEN}[ RUN      ]${NORMAL} push content to /system and /vendor" >&2
+echo "${GREEN}[ RUN      ]${NORMAL} push content to ${MOUNTS}" >&2
 
 A="Hello World! $(date)"
-echo "${A}" | adb_sh cat - ">/system/hello"
-echo "${A}" | adb_sh cat - ">/vendor/hello"
-B="`adb_cat /system/hello`" ||
-  die "sytem hello"
-check_eq "${A}" "${B}" /system before reboot
-B="`adb_cat /vendor/hello`" ||
-  die "vendor hello"
-check_eq "${A}" "${B}" /vendor before reboot
+for i in ${MOUNTS}; do
+  echo "${A}" | adb_sh cat - ">${i}/hello"
+  B="`adb_cat ${i}/hello`" ||
+    die "${i#/} hello"
+  check_eq "${A}" "${B}" ${i} before reboot
+done
+echo "${A}" | adb_sh cat - ">/system/priv-app/hello"
+B="`adb_cat /system/priv-app/hello`" ||
+  die "system priv-app hello"
+check_eq "${A}" "${B}" /system/priv-app before reboot
+SYSTEM_DEVT=`adb_sh stat --format=%D /system/hello </dev/null`
+VENDOR_DEVT=`adb_sh stat --format=%D /vendor/hello </dev/null`
+SYSTEM_INO=`adb_sh stat --format=%i /system/hello </dev/null`
+VENDOR_INO=`adb_sh stat --format=%i /vendor/hello </dev/null`
+BASE_SYSTEM_DEVT=`adb_sh stat --format=%D /system/bin/stat </dev/null`
+BASE_VENDOR_DEVT=`adb_sh stat --format=%D /vendor/bin/stat </dev/null`
+check_eq "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" vendor and system devt
+check_ne "${SYSTEM_INO}" "${VENDOR_INO}" vendor and system inode
+if ${overlayfs_needed}; then
+  check_ne "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt
+  check_ne "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt
+else
+  check_eq "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt
+  check_eq "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt
+fi
+check_ne "${BASE_SYSTEM_DEVT}" "${BASE_VENDOR_DEVT}" --warning system/vendor devt
+[ -n "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] ||
+  die "system devt ${SYSTEM_DEVT} is major 0"
+[ -n "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] ||
+  die "vendor devt ${SYSTEM_DEVT} is major 0"
 
 # Download libc.so, append some gargage, push back, and check if the file
 # is updated.
@@ -961,8 +1293,16 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} reboot to confirm content persistent" >&2
 
+fixup_from_recovery() {
+  inRecovery || return 1
+  echo "${ORANGE}[    ERROR ]${NORMAL} Device in recovery" >&2
+  adb reboot </dev/null
+  adb_wait ${ADB_WAIT}
+}
+
 adb_reboot &&
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
+  fixup_from_recovery ||
   die "reboot after override content added failed `usb_status`"
 
 if ${overlayfs_needed}; then
@@ -985,16 +1325,36 @@
   B="`adb_cat /vendor/hello 2>&1`"
   check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root
   echo "${GREEN}[       OK ]${NORMAL} /vendor content correct MAC after reboot" >&2
+  # Feed unprivileged log with selinux denials as a result of overlays
+  wait_for_screen
+  adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null
 fi
-B="`adb_cat /system/hello`"
-check_eq "${A}" "${B}" /system after reboot
-echo "${GREEN}[       OK ]${NORMAL} /system content remains after reboot" >&2
+# If overlayfs has a nested security problem, this will fail.
+B="`adb_ls /system/`" ||
+  die "adb ls /system"
+[ X"${B}" != X"${B#*priv-app}" ] ||
+  die "adb ls /system/priv-app"
+B="`adb_cat /system/priv-app/hello`"
+check_eq "${A}" "${B}" /system/priv-app after reboot
 # Only root can read vendor if sepolicy permissions are as expected.
 adb_root ||
   die "adb root"
-B="`adb_cat /vendor/hello`"
-check_eq "${A}" "${B}" vendor after reboot
-echo "${GREEN}[       OK ]${NORMAL} /vendor content remains after reboot" >&2
+for i in ${MOUNTS}; do
+  B="`adb_cat ${i}/hello`"
+  check_eq "${A}" "${B}" ${i#/} after reboot
+  echo "${GREEN}[       OK ]${NORMAL} ${i} content remains after reboot" >&2
+done
+
+check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot
+check_eq "${VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/hello </dev/null`" vendor devt after reboot
+check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot
+check_eq "${VENDOR_INO}" "`adb_sh stat --format=%i /vendor/hello </dev/null`" vendor inode after reboot
+check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" base system devt after reboot
+check_eq "${BASE_VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/bin/stat </dev/null`" base system devt after reboot
+check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" devt for su after reboot
+
+# Feed log with selinux denials as a result of overlays
+adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null
 
 # Check if the updated libc.so is persistent after reboot.
 adb_root &&
@@ -1025,10 +1385,17 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} wrong vendor image, skipping"
 elif [ -z "${ANDROID_HOST_OUT}" ]; then
   echo "${ORANGE}[  WARNING ]${NORMAL} please run lunch, skipping"
+elif ! (
+          adb_cat /vendor/build.prop |
+          cmp -s ${ANDROID_PRODUCT_OUT}/vendor/build.prop
+       ) >/dev/null 2>/dev/null; then
+  echo "${ORANGE}[  WARNING ]${NORMAL} vendor image signature mismatch, skipping"
 else
-  adb reboot fastboot ||
+  wait_for_screen
+  avc_check
+  adb reboot fastboot </dev/null ||
     die "fastbootd not supported (wrong adb in path?)"
-  any_wait 2m &&
+  any_wait ${ADB_WAIT} &&
     inFastboot ||
     die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)"
   fastboot flash vendor ||
@@ -1069,8 +1436,9 @@
   fastboot reboot ||
     die "can not reboot out of fastboot"
   echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot"
-  adb_wait 2m ||
-    die "did not reboot after flash `usb_status`"
+  adb_wait ${ADB_WAIT} ||
+    fixup_from_recovery ||
+    die "did not reboot after formatting ${scratch_partition} `usb_status`"
   if ${overlayfs_needed}; then
     adb_root &&
       D=`adb_sh df -k </dev/null` &&
@@ -1090,6 +1458,12 @@
   fi
   B="`adb_cat /system/hello`"
   check_eq "${A}" "${B}" system after flash vendor
+  B="`adb_ls /system/`" ||
+    die "adb ls /system"
+  [ X"${B}" != X"${B#*priv-app}" ] ||
+    die "adb ls /system/priv-app"
+  B="`adb_cat /system/priv-app/hello`"
+  check_eq "${A}" "${B}" system/priv-app after flash vendor
   adb_root ||
     die "adb root"
   B="`adb_cat /vendor/hello`"
@@ -1101,8 +1475,15 @@
     check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
              --warning vendor content after flash vendor
   fi
+
+  check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot
+  check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot
+  check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" base system devt after reboot
+  check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" devt for su after reboot
+
 fi
 
+wait_for_screen
 echo "${GREEN}[ RUN      ]${NORMAL} remove test content (cleanup)" >&2
 
 T=`adb_date`
@@ -1114,7 +1495,7 @@
   echo "${ORANGE}[  WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)"
   L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
   adb_reboot &&
-    adb_wait 2m &&
+    adb_wait ${ADB_WAIT} &&
     adb_root ||
     die "failed to reboot"
   T=`adb_date`
@@ -1124,27 +1505,33 @@
 echo "${H}"
 [ ${err} = 0 ] &&
   ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) &&
-  adb_sh rm /system/hello </dev/null ||
+  adb_sh rm /system/hello /system/priv-app/hello </dev/null ||
   ( [ -n "${L}" ] && echo "${L}" && false ) ||
   die -t ${T} "cleanup hello"
 B="`adb_cat /system/hello`"
 check_eq "cat: /system/hello: No such file or directory" "${B}" after rm
+B="`adb_cat /system/priv-app/hello`"
+check_eq "cat: /system/priv-app/hello: No such file or directory" "${B}" after rm
 B="`adb_cat /vendor/hello`"
 check_eq "cat: /vendor/hello: No such file or directory" "${B}" after rm
+for i in ${MOUNTS}; do
+  adb_sh rm ${i}/hello </dev/null 2>/dev/null || true
+done
 
-if [ -n "${scratch_partition}" ]; then
+if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then
 
   echo "${GREEN}[ RUN      ]${NORMAL} test fastboot flash to ${scratch_partition} recovery" >&2
 
-  adb reboot fastboot ||
+  avc_check
+  adb reboot fastboot </dev/null ||
     die "Reboot into fastbootd"
   img=${TMPDIR}/adb-remount-test-${$}.img
   cleanup() {
     rm ${img}
   }
   dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
-    fastboot_wait 2m ||
-    die "reboot into fastboot `usb_status`"
+    fastboot_wait ${FASTBOOT_WAIT} ||
+    die "reboot into fastboot to flash scratch `usb_status`"
   fastboot flash --force ${scratch_partition} ${img}
   err=${?}
   cleanup
@@ -1155,9 +1542,9 @@
     die "can not reboot out of fastboot"
   [ 0 -eq ${err} ] ||
     die "fastboot flash ${scratch_partition}"
-  adb_wait 2m &&
+  adb_wait ${ADB_WAIT} &&
     adb_root ||
-    die "did not reboot after flash"
+    die "did not reboot after flashing empty ${scratch_partition} `usb_status`"
   T=`adb_date`
   D=`adb disable-verity 2>&1`
   err=${?}
@@ -1165,7 +1552,7 @@
   then
     echo "${ORANGE}[  WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash"
     adb_reboot &&
-      adb_wait 2m &&
+      adb_wait ${ADB_WAIT} &&
       adb_root ||
       die "failed to reboot"
     T=`adb_date`
@@ -1191,9 +1578,25 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} test raw remount commands" >&2
 
+fixup_from_fastboot() {
+  inFastboot || return 1
+  if [ -n "${ACTIVE_SLOT}" ]; then
+    local active_slot=`get_active_slot`
+    if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+      echo "${ORANGE}[    ERROR ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+    else
+      echo "${ORANGE}[    ERROR ]${NORMAL} Active slot to be set to ${ACTIVE_SLOT}"
+    fi >&2
+    fastboot --set-active=${ACTIVE_SLOT}
+  fi
+  fastboot reboot
+  adb_wait ${ADB_WAIT}
+}
+
 # Prerequisite is a prepped device from above.
 adb_reboot &&
-  adb_wait 2m ||
+  adb_wait ${ADB_WAIT} ||
+  fixup_from_fastboot ||
   die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/vendor is not read-only"
@@ -1205,8 +1608,9 @@
 
 # Prerequisite is a prepped device from above.
 adb_reboot &&
-  adb_wait 2m ||
-  die "lost device after reboot to ro state (USB stack broken?)"
+  adb_wait ${ADB_WAIT} ||
+  fixup_from_fastboot ||
+  die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/vendor is not read-only"
 adb_su remount vendor </dev/null ||
@@ -1225,30 +1629,50 @@
     die "/${d}/overlay wipe"
 done
 adb_reboot &&
-  adb_wait 2m ||
-  die "lost device after reboot after wipe (USB stack broken?)"
+  adb_wait ${ADB_WAIT} ||
+  fixup_from_fastboot ||
+  die "lost device after reboot after wipe `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/vendor is not read-only"
 adb_su remount vendor </dev/null ||
   die "remount command"
+adb_su df -k </dev/null | skip_unrelated_mounts
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null ||
   die "/vendor is not read-write"
-adb_sh grep " /system .* rw," /proc/mounts >/dev/null </dev/null &&
+adb_sh grep " \(/system\|/\) .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/system is not read-only"
 echo "${GREEN}[       OK ]${NORMAL} remount command works from scratch" >&2
 
-restore
-err=${?}
+if ! restore; then
+  restore() {
+    true
+  }
+  die "failed to restore verity after remount from scratch test"
+fi
 
-if [ ${err} = 0 ] && ${overlayfs_supported}; then
+err=0
+
+if ${overlayfs_supported}; then
   echo "${GREEN}[ RUN      ]${NORMAL} test 'adb remount -R'" >&2
-  adb_root &&
-    adb remount -R &&
-    adb_wait 2m ||
-    die "adb remount -R"
+  avc_check
+  adb_root ||
+    die "adb root in preparation for adb remount -R"
+  T=`adb_date`
+  adb remount -R
+  err=${?}
+  if [ "${err}" != 0 ]; then
+    die -t ${T} "adb remount -R = ${err}"
+  fi
+  sleep 2
+  adb_wait ${ADB_WAIT} ||
+    die "waiting for device after adb remount -R `usb_status`"
   if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
-       "2" = "`get_property partition.system.verified`" ]; then
-    die "remount -R command failed to disable verity"
+       "2" = "`get_property partition.system.verified`" ] &&
+     [ -n "`get_property ro.boot.verifiedbootstate`" -o \
+       -n "`get_property partition.system.verified`" ]; then
+    die "remount -R command failed to disable verity
+${INDENT}ro.boot.verifiedbootstate=\"`get_property ro.boot.verifiedbootstate`\"
+${INDENT}partition.system.verified=\"`get_property partition.system.verified`\""
   fi
 
   echo "${GREEN}[       OK ]${NORMAL} 'adb remount -R' command" >&2
@@ -1262,7 +1686,7 @@
 }
 
 [ ${err} = 0 ] ||
-  die "failed to restore verity" >&2
+  die "failed to restore verity"
 
 echo "${GREEN}[  PASSED  ]${NORMAL} adb remount" >&2
 
diff --git a/fs_mgr/tests/file_wait_test.cpp b/fs_mgr/tests/file_wait_test.cpp
new file mode 100644
index 0000000..cc8b143
--- /dev/null
+++ b/fs_mgr/tests/file_wait_test.cpp
@@ -0,0 +1,91 @@
+// 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 <chrono>
+#include <string>
+#include <thread>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <fs_mgr/file_wait.h>
+#include <gtest/gtest.h>
+
+using namespace std::literals;
+using android::base::unique_fd;
+using android::fs_mgr::WaitForFile;
+using android::fs_mgr::WaitForFileDeleted;
+
+class FileWaitTest : public ::testing::Test {
+  protected:
+    void SetUp() override {
+        const ::testing::TestInfo* tinfo = ::testing::UnitTest::GetInstance()->current_test_info();
+        test_file_ = temp_dir_.path + "/"s + tinfo->name();
+    }
+
+    void TearDown() override { unlink(test_file_.c_str()); }
+
+    TemporaryDir temp_dir_;
+    std::string test_file_;
+};
+
+TEST_F(FileWaitTest, FileExists) {
+    unique_fd fd(open(test_file_.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0700));
+    ASSERT_GE(fd, 0);
+
+    ASSERT_TRUE(WaitForFile(test_file_, 500ms));
+    ASSERT_FALSE(WaitForFileDeleted(test_file_, 500ms));
+}
+
+TEST_F(FileWaitTest, FileDoesNotExist) {
+    ASSERT_FALSE(WaitForFile(test_file_, 500ms));
+    ASSERT_TRUE(WaitForFileDeleted(test_file_, 500ms));
+}
+
+TEST_F(FileWaitTest, CreateAsync) {
+    std::thread thread([this] {
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+        unique_fd fd(open(test_file_.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0700));
+    });
+    EXPECT_TRUE(WaitForFile(test_file_, 3s));
+    thread.join();
+}
+
+TEST_F(FileWaitTest, CreateOtherAsync) {
+    std::thread thread([this] {
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+        unique_fd fd(open(test_file_.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0700));
+    });
+    EXPECT_FALSE(WaitForFile(test_file_ + ".wontexist", 2s));
+    thread.join();
+}
+
+TEST_F(FileWaitTest, DeleteAsync) {
+    // Note: need to close the file, otherwise inotify considers it not deleted.
+    {
+        unique_fd fd(open(test_file_.c_str(), O_CREAT | O_TRUNC | O_RDWR, 0700));
+        ASSERT_GE(fd, 0);
+    }
+
+    std::thread thread([this] {
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+        unlink(test_file_.c_str());
+    });
+    EXPECT_TRUE(WaitForFileDeleted(test_file_, 3s));
+    thread.join();
+}
+
+TEST_F(FileWaitTest, BadPath) {
+    ASSERT_FALSE(WaitForFile("/this/path/does/not/exist", 5ms));
+    EXPECT_EQ(errno, ENOENT);
+}
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 72afa69..c5adea6 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -179,6 +179,7 @@
                 {"nodiratime", MS_NODIRATIME},
                 {"ro", MS_RDONLY},
                 {"rw", 0},
+                {"sync", MS_SYNCHRONOUS},
                 {"remount", MS_REMOUNT},
                 {"bind", MS_BIND},
                 {"rec", MS_REC},
@@ -197,7 +198,7 @@
         if (!(entry.flags & MS_RDONLY)) {
             fs_options.emplace("rw");
         }
-        EXPECT_EQ(mnt_opts, fs_options);
+        EXPECT_EQ(mnt_opts, fs_options) << "At line " << i;
         ++i;
     }
     EXPECT_EQ(i, fstab.size());
@@ -394,7 +395,7 @@
     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 none1       swap   defaults      encryptable=,forceencrypt=,fileencryption=,keydirectory=,length=,swapprio=,zramsize=,max_comp_streams=,avb=,reservedsize=,eraseblk=,logicalblk=,sysfs_path=,zram_loopback_path=,zram_loopback_size=,zram_backing_dev_path=
 
 source none2       swap   defaults      forcefdeorfbe=
 
@@ -413,7 +414,6 @@
     }
     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);
@@ -421,8 +421,7 @@
     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("", entry->encryption_options);
     EXPECT_EQ(0, entry->erase_blk_size);
     EXPECT_EQ(0, entry->logical_blk_size);
     EXPECT_EQ("", entry->sysfs_path);
@@ -437,13 +436,11 @@
         flags.crypt = true;
         flags.force_crypt = true;
         flags.file_encryption = true;
-        flags.verify = true;
         flags.avb = true;
         EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
     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);
@@ -451,8 +448,7 @@
     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("", entry->encryption_options);
     EXPECT_EQ(0, entry->erase_blk_size);
     EXPECT_EQ(0, entry->logical_blk_size);
     EXPECT_EQ("", entry->sysfs_path);
@@ -461,15 +457,14 @@
     EXPECT_EQ("", entry->zram_backing_dev_path);
     entry++;
 
-    // forcefdeorfbe sets file_contents_mode and file_names_mode by default, so test it separately.
+    // forcefdeorfbe has its own encryption_options defaults, so test it separately.
     EXPECT_EQ("none2", entry->mount_point);
     {
         FstabEntry::FsMgrFlags flags = {};
         flags.force_fde_or_fbe = true;
         EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
-    EXPECT_EQ("aes-256-xts", entry->file_contents_mode);
-    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
+    EXPECT_EQ("aes-256-xts:aes-256-cts", entry->encryption_options);
     EXPECT_EQ("", entry->key_loc);
 }
 
@@ -639,29 +634,6 @@
     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::WriteStringToFile(fstab_contents, tf.path));
-
-    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 = {};
-    flags.verify = true;
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-
-    EXPECT_EQ("/dir/key", entry->verity_loc);
-}
-
 TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_ForceEncrypt) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
@@ -706,32 +678,21 @@
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
 
     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);
+    EXPECT_EQ("aes-256-xts:aes-256-cts", entry->encryption_options);
 }
 
 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:
+source none0       swap   defaults      fileencryption=aes-256-xts:aes-256-cts:v1
 )fs";
 
     ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path));
 
     Fstab fstab;
     EXPECT_TRUE(ReadFstabFromFile(tf.path, &fstab));
-    ASSERT_EQ(11U, fstab.size());
+    ASSERT_EQ(1U, fstab.size());
 
     FstabEntry::FsMgrFlags flags = {};
     flags.file_encryption = true;
@@ -739,68 +700,7 @@
     auto entry = fstab.begin();
     EXPECT_EQ("none0", entry->mount_point);
     EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("", entry->file_contents_mode);
-    EXPECT_EQ("", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none1", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    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_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    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_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("adiantum", entry->file_contents_mode);
-    EXPECT_EQ("adiantum", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none4", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("adiantum", entry->file_contents_mode);
-    EXPECT_EQ("aes-256-heh", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none5", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("ice", entry->file_contents_mode);
-    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none6", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("ice", entry->file_contents_mode);
-    EXPECT_EQ("", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none7", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("ice", entry->file_contents_mode);
-    EXPECT_EQ("aes-256-cts", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none8", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("ice", entry->file_contents_mode);
-    EXPECT_EQ("aes-256-heh", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none9", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("ice", entry->file_contents_mode);
-    EXPECT_EQ("adiantum", entry->file_names_mode);
-
-    entry++;
-    EXPECT_EQ("none10", entry->mount_point);
-    EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
-    EXPECT_EQ("", entry->file_contents_mode);
-    EXPECT_EQ("", entry->file_names_mode);
+    EXPECT_EQ("aes-256-xts:aes-256-cts:v1", entry->encryption_options);
 }
 
 TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_MaxCompStreams) {
@@ -1062,3 +962,21 @@
     EXPECT_EQ("none5", entry->mount_point);
     EXPECT_EQ("/dev/path2", entry->zram_backing_dev_path);
 }
+
+TEST(fs_mgr, DefaultFstabContainsUserdata) {
+    Fstab fstab;
+    ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
+    ASSERT_NE(nullptr, GetEntryForMountPoint(&fstab, "/data"))
+            << "Default fstab doesn't contain /data entry";
+}
+
+TEST(fs_mgr, UserdataMountedFromDefaultFstab) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
+    Fstab fstab;
+    ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
+    ASSERT_NE(nullptr, GetMountedEntryForUserdata(&fstab))
+            << "/data wasn't mounted from default fstab";
+}
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 9309aad..2738457 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -38,15 +38,7 @@
 #include <vector>
 
 using namespace std::literals::string_literals;
-
-using DeviceMapper = ::android::dm::DeviceMapper;
-using DmTable = ::android::dm::DmTable;
-using DmTarget = ::android::dm::DmTarget;
-using DmTargetLinear = ::android::dm::DmTargetLinear;
-using DmTargetZero = ::android::dm::DmTargetZero;
-using DmTargetAndroidVerity = ::android::dm::DmTargetAndroidVerity;
-using DmTargetBow = ::android::dm::DmTargetBow;
-using DmTargetTypeInfo = ::android::dm::DmTargetTypeInfo;
+using namespace android::dm;
 using DmBlockDevice = ::android::dm::DeviceMapper::DmBlockDevice;
 
 static int Usage(void) {
@@ -57,6 +49,10 @@
     std::cerr << "  delete <dm-name>" << std::endl;
     std::cerr << "  list <devices | targets> [-v]" << std::endl;
     std::cerr << "  getpath <dm-name>" << std::endl;
+    std::cerr << "  info <dm-name>" << std::endl;
+    std::cerr << "  status <dm-name>" << std::endl;
+    std::cerr << "  resume <dm-name>" << std::endl;
+    std::cerr << "  suspend <dm-name>" << std::endl;
     std::cerr << "  table <dm-name>" << std::endl;
     std::cerr << "  help" << std::endl;
     std::cerr << std::endl;
@@ -122,6 +118,62 @@
             }
             std::string block_device = NextArg();
             return std::make_unique<DmTargetBow>(start_sector, num_sectors, block_device);
+        } else if (target_type == "snapshot-origin") {
+            if (!HasArgs(1)) {
+                std::cerr << "Expected \"snapshot-origin\" <block_device>" << std::endl;
+                return nullptr;
+            }
+            std::string block_device = NextArg();
+            return std::make_unique<DmTargetSnapshotOrigin>(start_sector, num_sectors,
+                                                            block_device);
+        } else if (target_type == "snapshot") {
+            if (!HasArgs(4)) {
+                std::cerr
+                        << "Expected \"snapshot\" <block_device> <block_device> <mode> <chunk_size>"
+                        << std::endl;
+                return nullptr;
+            }
+            std::string base_device = NextArg();
+            std::string cow_device = NextArg();
+            std::string mode_str = NextArg();
+            std::string chunk_size_str = NextArg();
+
+            SnapshotStorageMode mode;
+            if (mode_str == "P") {
+                mode = SnapshotStorageMode::Persistent;
+            } else if (mode_str == "N") {
+                mode = SnapshotStorageMode::Transient;
+            } else {
+                std::cerr << "Unrecognized mode: " << mode_str << "\n";
+                return nullptr;
+            }
+
+            uint32_t chunk_size;
+            if (!android::base::ParseUint(chunk_size_str, &chunk_size)) {
+                std::cerr << "Chunk size must be an unsigned integer.\n";
+                return nullptr;
+            }
+            return std::make_unique<DmTargetSnapshot>(start_sector, num_sectors, base_device,
+                                                      cow_device, mode, chunk_size);
+        } else if (target_type == "snapshot-merge") {
+            if (!HasArgs(3)) {
+                std::cerr
+                        << "Expected \"snapshot-merge\" <block_device> <block_device> <chunk_size>"
+                        << std::endl;
+                return nullptr;
+            }
+            std::string base_device = NextArg();
+            std::string cow_device = NextArg();
+            std::string chunk_size_str = NextArg();
+            SnapshotStorageMode mode = SnapshotStorageMode::Merge;
+
+            uint32_t chunk_size;
+            if (!android::base::ParseUint(chunk_size_str, &chunk_size)) {
+                std::cerr << "Chunk size must be an unsigned integer.\n";
+                return nullptr;
+            }
+            return std::make_unique<DmTargetSnapshot>(start_sector, num_sectors, base_device,
+                                                      cow_device, mode, chunk_size);
         } else {
             std::cerr << "Unrecognized target type: " << target_type << std::endl;
             return nullptr;
@@ -145,19 +197,12 @@
     char** argv_;
 };
 
-static int DmCreateCmdHandler(int argc, char** argv) {
-    if (argc < 1) {
-        std::cerr << "Usage: dmctl create <dm-name> [-ro] <targets...>" << std::endl;
-        return -EINVAL;
-    }
-    std::string name = argv[0];
-
+static bool parse_table_args(DmTable* table, int argc, char** argv) {
     // Parse extended options first.
-    DmTable table;
     int arg_index = 1;
     while (arg_index < argc && argv[arg_index][0] == '-') {
         if (strcmp(argv[arg_index], "-ro") == 0) {
-            table.set_readonly(true);
+            table->set_readonly(true);
             arg_index++;
         } else {
             std::cerr << "Unrecognized option: " << argv[arg_index] << std::endl;
@@ -169,15 +214,30 @@
     TargetParser parser(argc - arg_index, argv + arg_index);
     while (parser.More()) {
         std::unique_ptr<DmTarget> target = parser.Next();
-        if (!target || !table.AddTarget(std::move(target))) {
+        if (!target || !table->AddTarget(std::move(target))) {
             return -EINVAL;
         }
     }
 
-    if (table.num_targets() == 0) {
+    if (table->num_targets() == 0) {
         std::cerr << "Must define at least one target." << std::endl;
         return -EINVAL;
     }
+    return 0;
+}
+
+static int DmCreateCmdHandler(int argc, char** argv) {
+    if (argc < 1) {
+        std::cerr << "Usage: dmctl create <dm-name> [-ro] <targets...>" << std::endl;
+        return -EINVAL;
+    }
+    std::string name = argv[0];
+
+    DmTable table;
+    int ret = parse_table_args(&table, argc, argv);
+    if (ret) {
+        return ret;
+    }
 
     DeviceMapper& dm = DeviceMapper::Instance();
     if (!dm.CreateDevice(name, table)) {
@@ -203,6 +263,27 @@
     return 0;
 }
 
+static int DmReplaceCmdHandler(int argc, char** argv) {
+    if (argc < 1) {
+        std::cerr << "Usage: dmctl replace <dm-name> <targets...>" << std::endl;
+        return -EINVAL;
+    }
+    std::string name = argv[0];
+
+    DmTable table;
+    int ret = parse_table_args(&table, argc, argv);
+    if (ret) {
+        return ret;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.LoadTableAndActivate(name, table)) {
+        std::cerr << "Failed to replace device-mapper table to: " << name << std::endl;
+        return -EIO;
+    }
+    return 0;
+}
+
 static int DmListTargets(DeviceMapper& dm, [[maybe_unused]] int argc,
                          [[maybe_unused]] char** argv) {
     std::vector<DmTargetTypeInfo> targets;
@@ -308,7 +389,42 @@
     return 0;
 }
 
-static int TableCmdHandler(int argc, char** argv) {
+static int InfoCmdHandler(int argc, char** argv) {
+    if (argc != 1) {
+        std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
+        return -EINVAL;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    auto info = dm.GetDetailedInfo(argv[0]);
+    if (!info) {
+        std::cerr << "Invalid device \"" << argv[0] << "\"." << std::endl;
+        return -EINVAL;
+    }
+
+    constexpr int spacing = 14;
+    std::cout << std::left << std::setw(spacing) << "device"
+              << ": " << argv[0] << std::endl;
+    std::cout << std::left << std::setw(spacing) << "active"
+              << ": " << std::boolalpha << !info->IsSuspended() << std::endl;
+    std::cout << std::left << std::setw(spacing) << "access"
+              << ": ";
+    if (info->IsReadOnly()) {
+        std::cout << "ro ";
+    } else {
+        std::cout << "rw ";
+    }
+    std::cout << std::endl;
+    std::cout << std::left << std::setw(spacing) << "activeTable"
+              << ": " << std::boolalpha << info->IsActiveTablePresent() << std::endl;
+    std::cout << std::left << std::setw(spacing) << "inactiveTable"
+              << ": " << std::boolalpha << info->IsInactiveTablePresent() << std::endl;
+    std::cout << std::left << std::setw(spacing) << "bufferFull"
+              << ": " << std::boolalpha << info->IsBufferFull() << std::endl;
+    return 0;
+}
+
+static int DumpTable(const std::string& mode, int argc, char** argv) {
     if (argc != 1) {
         std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
         return -EINVAL;
@@ -316,9 +432,18 @@
 
     DeviceMapper& dm = DeviceMapper::Instance();
     std::vector<DeviceMapper::TargetInfo> table;
-    if (!dm.GetTableInfo(argv[0], &table)) {
-        std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
-        return -EINVAL;
+    if (mode == "status") {
+        if (!dm.GetTableStatus(argv[0], &table)) {
+            std::cerr << "Could not query table status of device \"" << argv[0] << "\"."
+                      << std::endl;
+            return -EINVAL;
+        }
+    } else if (mode == "table") {
+        if (!dm.GetTableInfo(argv[0], &table)) {
+            std::cerr << "Could not query table status of device \"" << argv[0] << "\"."
+                      << std::endl;
+            return -EINVAL;
+        }
     }
     std::cout << "Targets in the device-mapper table for " << argv[0] << ":" << std::endl;
     for (const auto& target : table) {
@@ -333,14 +458,55 @@
     return 0;
 }
 
+static int TableCmdHandler(int argc, char** argv) {
+    return DumpTable("table", argc, argv);
+}
+
+static int StatusCmdHandler(int argc, char** argv) {
+    return DumpTable("status", argc, argv);
+}
+
+static int ResumeCmdHandler(int argc, char** argv) {
+    if (argc != 1) {
+        std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
+        return -EINVAL;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.ChangeState(argv[0], DmDeviceState::ACTIVE)) {
+        std::cerr << "Could not resume device \"" << argv[0] << "\"." << std::endl;
+        return -EINVAL;
+    }
+    return 0;
+}
+
+static int SuspendCmdHandler(int argc, char** argv) {
+    if (argc != 1) {
+        std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
+        return -EINVAL;
+    }
+
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.ChangeState(argv[0], DmDeviceState::SUSPENDED)) {
+        std::cerr << "Could not suspend device \"" << argv[0] << "\"." << std::endl;
+        return -EINVAL;
+    }
+    return 0;
+}
+
 static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
         // clang-format off
         {"create", DmCreateCmdHandler},
         {"delete", DmDeleteCmdHandler},
+        {"replace", DmReplaceCmdHandler},
         {"list", DmListCmdHandler},
         {"help", HelpCmdHandler},
         {"getpath", GetPathCmdHandler},
+        {"info", InfoCmdHandler},
         {"table", TableCmdHandler},
+        {"status", StatusCmdHandler},
+        {"resume", ResumeCmdHandler},
+        {"suspend", SuspendCmdHandler},
         // clang-format on
 };
 
diff --git a/gatekeeperd/Android.bp b/gatekeeperd/Android.bp
index 2b7db79..27a6452 100644
--- a/gatekeeperd/Android.bp
+++ b/gatekeeperd/Android.bp
@@ -23,8 +23,6 @@
         "-Wunused",
     ],
     srcs: [
-        "SoftGateKeeperDevice.cpp",
-        "IGateKeeperService.cpp",
         "gatekeeperd.cpp",
     ],
 
@@ -40,12 +38,45 @@
         "libkeystore_aidl",
         "libkeystore_binder",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "android.hardware.gatekeeper@1.0",
+        "libgatekeeper_aidl",
     ],
 
     static_libs: ["libscrypt_static"],
     include_dirs: ["external/scrypt/lib/crypto"],
     init_rc: ["gatekeeperd.rc"],
 }
+
+filegroup {
+    name: "gatekeeper_aidl",
+    srcs: [
+        "binder/android/service/gatekeeper/IGateKeeperService.aidl",
+    ],
+    path: "binder",
+}
+
+cc_library_shared {
+    name: "libgatekeeper_aidl",
+    srcs: [
+        ":gatekeeper_aidl",
+        "GateKeeperResponse.cpp",
+    ],
+    aidl: {
+        export_aidl_headers: true,
+        include_dirs: [
+            "system/core/gatekeeperd/binder",
+            "frameworks/base/core/java/",
+        ],
+    },
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
+}
diff --git a/gatekeeperd/GateKeeperResponse.cpp b/gatekeeperd/GateKeeperResponse.cpp
new file mode 100644
index 0000000..ca0c98f
--- /dev/null
+++ b/gatekeeperd/GateKeeperResponse.cpp
@@ -0,0 +1,83 @@
+/*
+**
+** Copyright 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.
+*/
+
+#define LOG_TAG "gatekeeperd"
+
+#include <gatekeeper/GateKeeperResponse.h>
+
+#include <binder/Parcel.h>
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace service {
+namespace gatekeeper {
+
+status_t GateKeeperResponse::readFromParcel(const Parcel* in) {
+    if (in == nullptr) {
+        LOG(ERROR) << "readFromParcel got null in parameter";
+        return BAD_VALUE;
+    }
+    timeout_ = 0;
+    should_reenroll_ = false;
+    payload_ = {};
+    response_code_ = ResponseCode(in->readInt32());
+    if (response_code_ == ResponseCode::OK) {
+        should_reenroll_ = in->readInt32();
+        ssize_t length = in->readInt32();
+        if (length > 0) {
+            length = in->readInt32();
+            const uint8_t* buf = reinterpret_cast<const uint8_t*>(in->readInplace(length));
+            if (buf == nullptr) {
+                LOG(ERROR) << "readInplace returned null buffer for length " << length;
+                return BAD_VALUE;
+            }
+            payload_.resize(length);
+            std::copy(buf, buf + length, payload_.data());
+        }
+    } else if (response_code_ == ResponseCode::RETRY) {
+        timeout_ = in->readInt32();
+    }
+    return NO_ERROR;
+}
+status_t GateKeeperResponse::writeToParcel(Parcel* out) const {
+    if (out == nullptr) {
+        LOG(ERROR) << "writeToParcel got null out parameter";
+        return BAD_VALUE;
+    }
+    out->writeInt32(int32_t(response_code_));
+    if (response_code_ == ResponseCode::OK) {
+        out->writeInt32(should_reenroll_);
+        out->writeInt32(payload_.size());
+        if (payload_.size() != 0) {
+            out->writeInt32(payload_.size());
+            uint8_t* buf = reinterpret_cast<uint8_t*>(out->writeInplace(payload_.size()));
+            if (buf == nullptr) {
+                LOG(ERROR) << "writeInplace returned null buffer for length " << payload_.size();
+                return BAD_VALUE;
+            }
+            std::copy(payload_.begin(), payload_.end(), buf);
+        }
+    } else if (response_code_ == ResponseCode::RETRY) {
+        out->writeInt32(timeout_);
+    }
+    return NO_ERROR;
+}
+
+}  // namespace gatekeeper
+}  // namespace service
+}  // namespace android
diff --git a/gatekeeperd/IGateKeeperService.cpp b/gatekeeperd/IGateKeeperService.cpp
deleted file mode 100644
index 43d5708..0000000
--- a/gatekeeperd/IGateKeeperService.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2015, 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 "GateKeeperService"
-#include <utils/Log.h>
-
-#include "IGateKeeperService.h"
-
-namespace android {
-
-const android::String16 IGateKeeperService::descriptor("android.service.gatekeeper.IGateKeeperService");
-const android::String16& IGateKeeperService::getInterfaceDescriptor() const {
-    return IGateKeeperService::descriptor;
-}
-
-status_t BnGateKeeperService::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
-    switch(code) {
-        case ENROLL: {
-            CHECK_INTERFACE(IGateKeeperService, data, reply);
-            uint32_t uid = data.readInt32();
-
-            ssize_t currentPasswordHandleSize = data.readInt32();
-            const uint8_t *currentPasswordHandle =
-                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
-            if (!currentPasswordHandle) currentPasswordHandleSize = 0;
-
-            ssize_t currentPasswordSize = data.readInt32();
-            const uint8_t *currentPassword =
-                    static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
-            if (!currentPassword) currentPasswordSize = 0;
-
-            ssize_t desiredPasswordSize = data.readInt32();
-            const uint8_t *desiredPassword =
-                    static_cast<const uint8_t *>(data.readInplace(desiredPasswordSize));
-            if (!desiredPassword) desiredPasswordSize = 0;
-
-            uint8_t *out = NULL;
-            uint32_t outSize = 0;
-            int ret = enroll(uid, currentPasswordHandle, currentPasswordHandleSize,
-                    currentPassword, currentPasswordSize, desiredPassword,
-                    desiredPasswordSize, &out, &outSize);
-
-            reply->writeNoException();
-            reply->writeInt32(1);
-            if (ret == 0 && outSize > 0 && out != NULL) {
-                reply->writeInt32(GATEKEEPER_RESPONSE_OK);
-                reply->writeInt32(0);
-                reply->writeInt32(outSize);
-                reply->writeInt32(outSize);
-                void *buf = reply->writeInplace(outSize);
-                memcpy(buf, out, outSize);
-                delete[] out;
-            } else if (ret > 0) {
-                reply->writeInt32(GATEKEEPER_RESPONSE_RETRY);
-                reply->writeInt32(ret);
-            } else {
-                reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
-            }
-            return OK;
-        }
-        case VERIFY: {
-            CHECK_INTERFACE(IGateKeeperService, data, reply);
-            uint32_t uid = data.readInt32();
-            ssize_t currentPasswordHandleSize = data.readInt32();
-            const uint8_t *currentPasswordHandle =
-                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
-            if (!currentPasswordHandle) currentPasswordHandleSize = 0;
-
-            ssize_t currentPasswordSize = data.readInt32();
-            const uint8_t *currentPassword =
-                static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
-            if (!currentPassword) currentPasswordSize = 0;
-
-            bool request_reenroll = false;
-            int ret = verify(uid, (uint8_t *) currentPasswordHandle,
-                    currentPasswordHandleSize, (uint8_t *) currentPassword, currentPasswordSize,
-                    &request_reenroll);
-
-            reply->writeNoException();
-            reply->writeInt32(1);
-            if (ret == 0) {
-                reply->writeInt32(GATEKEEPER_RESPONSE_OK);
-                reply->writeInt32(request_reenroll ? 1 : 0);
-                reply->writeInt32(0); // no payload returned from this call
-            } else if (ret > 0) {
-                reply->writeInt32(GATEKEEPER_RESPONSE_RETRY);
-                reply->writeInt32(ret);
-            } else {
-                reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
-            }
-            return OK;
-        }
-        case VERIFY_CHALLENGE: {
-            CHECK_INTERFACE(IGateKeeperService, data, reply);
-            uint32_t uid = data.readInt32();
-            uint64_t challenge = data.readInt64();
-            ssize_t currentPasswordHandleSize = data.readInt32();
-            const uint8_t *currentPasswordHandle =
-                    static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
-            if (!currentPasswordHandle) currentPasswordHandleSize = 0;
-
-            ssize_t currentPasswordSize = data.readInt32();
-            const uint8_t *currentPassword =
-                static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
-            if (!currentPassword) currentPasswordSize = 0;
-
-
-            uint8_t *out = NULL;
-            uint32_t outSize = 0;
-            bool request_reenroll = false;
-            int ret = verifyChallenge(uid, challenge, (uint8_t *) currentPasswordHandle,
-                    currentPasswordHandleSize, (uint8_t *) currentPassword, currentPasswordSize,
-                    &out, &outSize, &request_reenroll);
-            reply->writeNoException();
-            reply->writeInt32(1);
-            if (ret == 0 && outSize > 0 && out != NULL) {
-                reply->writeInt32(GATEKEEPER_RESPONSE_OK);
-                reply->writeInt32(request_reenroll ? 1 : 0);
-                reply->writeInt32(outSize);
-                reply->writeInt32(outSize);
-                void *buf = reply->writeInplace(outSize);
-                memcpy(buf, out, outSize);
-                delete[] out;
-            } else if (ret > 0) {
-                reply->writeInt32(GATEKEEPER_RESPONSE_RETRY);
-                reply->writeInt32(ret);
-            } else {
-                reply->writeInt32(GATEKEEPER_RESPONSE_ERROR);
-            }
-            return OK;
-        }
-        case GET_SECURE_USER_ID: {
-            CHECK_INTERFACE(IGateKeeperService, data, reply);
-            uint32_t uid = data.readInt32();
-            uint64_t sid = getSecureUserId(uid);
-            reply->writeNoException();
-            reply->writeInt64(sid);
-            return OK;
-        }
-        case CLEAR_SECURE_USER_ID: {
-            CHECK_INTERFACE(IGateKeeperService, data, reply);
-            uint32_t uid = data.readInt32();
-            clearSecureUserId(uid);
-            reply->writeNoException();
-            return OK;
-        }
-        case REPORT_DEVICE_SETUP_COMPLETE: {
-            CHECK_INTERFACE(IGateKeeperService, data, reply);
-            reportDeviceSetupComplete();
-            reply->writeNoException();
-            return OK;
-        }
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-};
-
-
-}; // namespace android
diff --git a/gatekeeperd/IGateKeeperService.h b/gatekeeperd/IGateKeeperService.h
deleted file mode 100644
index 2816efc..0000000
--- a/gatekeeperd/IGateKeeperService.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2015 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 IGATEKEEPER_SERVICE_H_
-#define IGATEKEEPER_SERVICE_H_
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-/*
- * This must be kept manually in sync with frameworks/base's IGateKeeperService.aidl
- */
-class IGateKeeperService : public IInterface {
-public:
-    enum {
-        ENROLL = IBinder::FIRST_CALL_TRANSACTION + 0,
-        VERIFY = IBinder::FIRST_CALL_TRANSACTION + 1,
-        VERIFY_CHALLENGE = IBinder::FIRST_CALL_TRANSACTION + 2,
-        GET_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 3,
-        CLEAR_SECURE_USER_ID = IBinder::FIRST_CALL_TRANSACTION + 4,
-        REPORT_DEVICE_SETUP_COMPLETE = IBinder::FIRST_CALL_TRANSACTION + 5,
-    };
-
-    enum {
-        GATEKEEPER_RESPONSE_OK = 0,
-        GATEKEEPER_RESPONSE_RETRY = 1,
-        GATEKEEPER_RESPONSE_ERROR = -1,
-    };
-
-    // DECLARE_META_INTERFACE - C++ client interface not needed
-    static const android::String16 descriptor;
-    virtual const android::String16& getInterfaceDescriptor() const;
-    IGateKeeperService() {}
-    virtual ~IGateKeeperService() {}
-
-    /**
-     * Enrolls a password with the GateKeeper. Returns 0 on success, negative on failure.
-     * Returns:
-     * - 0 on success
-     * - A timestamp T > 0 if the call has failed due to throttling and should not
-     *   be reattempted until T milliseconds have elapsed
-     * - -1 on failure
-     */
-    virtual int enroll(uint32_t uid,
-            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
-            const uint8_t *current_password, uint32_t current_password_length,
-            const uint8_t *desired_password, uint32_t desired_password_length,
-            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) = 0;
-
-    /**
-     * Verifies a password previously enrolled with the GateKeeper.
-     * Returns:
-     * - 0 on success
-     * - A timestamp T > 0 if the call has failed due to throttling and should not
-     *   be reattempted until T milliseconds have elapsed
-     * - -1 on failure
-     */
-    virtual int verify(uint32_t uid, const uint8_t *enrolled_password_handle,
-            uint32_t enrolled_password_handle_length,
-            const uint8_t *provided_password, uint32_t provided_password_length,
-            bool *request_reenroll) = 0;
-
-    /**
-     * Verifies a password previously enrolled with the GateKeeper.
-     * Returns:
-     * - 0 on success
-     * - A timestamp T > 0 if the call has failed due to throttling and should not
-     *   be reattempted until T milliseconds have elapsed
-     * - -1 on failure
-     */
-    virtual int verifyChallenge(uint32_t uid, uint64_t challenge,
-            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
-            const uint8_t *provided_password, uint32_t provided_password_length,
-            uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) = 0;
-    /**
-     * Returns the secure user ID for the provided android user
-     */
-    virtual uint64_t getSecureUserId(uint32_t uid) = 0;
-
-    /**
-     * Clears the secure user ID associated with the user.
-     */
-    virtual void clearSecureUserId(uint32_t uid) = 0;
-
-    /**
-     * Notifies gatekeeper that device setup has been completed and any potentially still existing
-     * state from before a factory reset can be cleaned up (if it has not been already).
-     */
-    virtual void reportDeviceSetupComplete() = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnGateKeeperService: public BnInterface<IGateKeeperService> {
-public:
-    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
-            uint32_t flags = 0);
-};
-
-} // namespace android
-
-#endif
-
diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h
deleted file mode 100644
index 5c03dcf..0000000
--- a/gatekeeperd/SoftGateKeeper.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2015 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 SOFT_GATEKEEPER_H_
-#define SOFT_GATEKEEPER_H_
-
-extern "C" {
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-
-#include <crypto_scrypt.h>
-}
-
-#include <android-base/memory.h>
-#include <gatekeeper/gatekeeper.h>
-
-#include <iostream>
-#include <unordered_map>
-#include <memory>
-
-namespace gatekeeper {
-
-struct fast_hash_t {
-    uint64_t salt;
-    uint8_t digest[SHA256_DIGEST_LENGTH];
-};
-
-class SoftGateKeeper : public GateKeeper {
-public:
-    static const uint32_t SIGNATURE_LENGTH_BYTES = 32;
-
-    // scrypt params
-    static const uint64_t N = 16384;
-    static const uint32_t r = 8;
-    static const uint32_t p = 1;
-
-    static const int MAX_UINT_32_CHARS = 11;
-
-    SoftGateKeeper() {
-        key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
-        memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
-    }
-
-    virtual ~SoftGateKeeper() {
-    }
-
-    virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const {
-        if (auth_token_key == NULL || length == NULL) return false;
-        *auth_token_key = key_.get();
-        *length = SIGNATURE_LENGTH_BYTES;
-        return true;
-    }
-
-    virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) {
-        if (password_key == NULL || length == NULL) return;
-        *password_key = key_.get();
-        *length = SIGNATURE_LENGTH_BYTES;
-    }
-
-    virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length,
-            const uint8_t *, uint32_t, const uint8_t *password,
-            uint32_t password_length, salt_t salt) const {
-        if (signature == NULL) return;
-        crypto_scrypt(password, password_length, reinterpret_cast<uint8_t *>(&salt),
-                sizeof(salt), N, r, p, signature, signature_length);
-    }
-
-    virtual void GetRandom(void *random, uint32_t requested_length) const {
-        if (random == NULL) return;
-        RAND_pseudo_bytes((uint8_t *) random, requested_length);
-    }
-
-    virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length,
-            const uint8_t *, uint32_t, const uint8_t *, const uint32_t) const {
-        if (signature == NULL) return;
-        memset(signature, 0, signature_length);
-    }
-
-    virtual uint64_t GetMillisecondsSinceBoot() const {
-        struct timespec time;
-        int res = clock_gettime(CLOCK_BOOTTIME, &time);
-        if (res < 0) return 0;
-        return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
-    }
-
-    virtual bool IsHardwareBacked() const {
-        return false;
-    }
-
-    virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record,
-            bool /* secure */) {
-        failure_record_t *stored = &failure_map_[uid];
-        if (user_id != stored->secure_user_id) {
-            stored->secure_user_id = user_id;
-            stored->last_checked_timestamp = 0;
-            stored->failure_counter = 0;
-        }
-        memcpy(record, stored, sizeof(*record));
-        return true;
-    }
-
-    virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) {
-        failure_record_t *stored = &failure_map_[uid];
-        stored->secure_user_id = user_id;
-        stored->last_checked_timestamp = 0;
-        stored->failure_counter = 0;
-        return true;
-    }
-
-    virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record, bool /* secure */) {
-        failure_map_[uid] = *record;
-        return true;
-    }
-
-    fast_hash_t ComputeFastHash(const SizedBuffer &password, uint64_t salt) {
-        fast_hash_t fast_hash;
-        size_t digest_size = password.length + sizeof(salt);
-        std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
-        memcpy(digest.get(), &salt, sizeof(salt));
-        memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length);
-
-        SHA256(digest.get(), digest_size, (uint8_t *) &fast_hash.digest);
-
-        fast_hash.salt = salt;
-        return fast_hash;
-    }
-
-    bool VerifyFast(const fast_hash_t &fast_hash, const SizedBuffer &password) {
-        fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
-        return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
-    }
-
-    bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
-        uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
-        FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
-        if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
-            return true;
-        } else {
-            if (GateKeeper::DoVerify(expected_handle, password)) {
-                uint64_t salt;
-                GetRandom(&salt, sizeof(salt));
-                fast_hash_map_[user_id] = ComputeFastHash(password, salt);
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-private:
-
-    typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
-    typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
-
-    std::unique_ptr<uint8_t[]> key_;
-    FailureRecordMap failure_map_;
-    FastHashMap fast_hash_map_;
-};
-}
-
-#endif // SOFT_GATEKEEPER_H_
diff --git a/gatekeeperd/SoftGateKeeperDevice.cpp b/gatekeeperd/SoftGateKeeperDevice.cpp
deleted file mode 100644
index f5e2ce6..0000000
--- a/gatekeeperd/SoftGateKeeperDevice.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2015 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 "SoftGateKeeper.h"
-#include "SoftGateKeeperDevice.h"
-
-namespace android {
-
-int SoftGateKeeperDevice::enroll(uint32_t uid,
-            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
-            const uint8_t *current_password, uint32_t current_password_length,
-            const uint8_t *desired_password, uint32_t desired_password_length,
-            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
-
-    if (enrolled_password_handle == NULL || enrolled_password_handle_length == NULL ||
-            desired_password == NULL || desired_password_length == 0)
-        return -EINVAL;
-
-    // Current password and current password handle go together
-    if (current_password_handle == NULL || current_password_handle_length == 0 ||
-            current_password == NULL || current_password_length == 0) {
-        current_password_handle = NULL;
-        current_password_handle_length = 0;
-        current_password = NULL;
-        current_password_length = 0;
-    }
-
-    SizedBuffer desired_password_buffer(desired_password_length);
-    memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length);
-
-    SizedBuffer current_password_handle_buffer(current_password_handle_length);
-    if (current_password_handle) {
-        memcpy(current_password_handle_buffer.buffer.get(), current_password_handle,
-                current_password_handle_length);
-    }
-
-    SizedBuffer current_password_buffer(current_password_length);
-    if (current_password) {
-        memcpy(current_password_buffer.buffer.get(), current_password, current_password_length);
-    }
-
-    EnrollRequest request(uid, &current_password_handle_buffer, &desired_password_buffer,
-            &current_password_buffer);
-    EnrollResponse response;
-
-    impl_->Enroll(request, &response);
-
-    if (response.error == ERROR_RETRY) {
-        return response.retry_timeout;
-    } else if (response.error != ERROR_NONE) {
-        return -EINVAL;
-    }
-
-    *enrolled_password_handle = response.enrolled_password_handle.buffer.release();
-    *enrolled_password_handle_length = response.enrolled_password_handle.length;
-    return 0;
-}
-
-int SoftGateKeeperDevice::verify(uint32_t uid,
-        uint64_t challenge, const uint8_t *enrolled_password_handle,
-        uint32_t enrolled_password_handle_length, const uint8_t *provided_password,
-        uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,
-        bool *request_reenroll) {
-
-    if (enrolled_password_handle == NULL ||
-            provided_password == NULL) {
-        return -EINVAL;
-    }
-
-    SizedBuffer password_handle_buffer(enrolled_password_handle_length);
-    memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle,
-            enrolled_password_handle_length);
-    SizedBuffer provided_password_buffer(provided_password_length);
-    memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length);
-
-    VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer);
-    VerifyResponse response;
-
-    impl_->Verify(request, &response);
-
-    if (response.error == ERROR_RETRY) {
-        return response.retry_timeout;
-    } else if (response.error != ERROR_NONE) {
-        return -EINVAL;
-    }
-
-    if (auth_token != NULL && auth_token_length != NULL) {
-       *auth_token = response.auth_token.buffer.release();
-       *auth_token_length = response.auth_token.length;
-    }
-
-    if (request_reenroll != NULL) {
-        *request_reenroll = response.request_reenroll;
-    }
-
-    return 0;
-}
-} // namespace android
diff --git a/gatekeeperd/SoftGateKeeperDevice.h b/gatekeeperd/SoftGateKeeperDevice.h
deleted file mode 100644
index e3dc068..0000000
--- a/gatekeeperd/SoftGateKeeperDevice.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2015 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 SOFT_GATEKEEPER_DEVICE_H_
-#define SOFT_GATEKEEPER_DEVICE_H_
-
-#include "SoftGateKeeper.h"
-
-#include <memory>
-
-using namespace gatekeeper;
-
-namespace android {
-
-/**
- * Software based GateKeeper implementation
- */
-class SoftGateKeeperDevice {
-public:
-    SoftGateKeeperDevice() {
-        impl_.reset(new SoftGateKeeper());
-    }
-
-   // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API.
-
-    /**
-     * Enrolls password_payload, which should be derived from a user selected pin or password,
-     * with the authentication factor private key used only for enrolling authentication
-     * factor data.
-     *
-     * Returns: 0 on success or an error code less than 0 on error.
-     * On error, enrolled_password_handle will not be allocated.
-     */
-    int enroll(uint32_t uid,
-            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
-            const uint8_t *current_password, uint32_t current_password_length,
-            const uint8_t *desired_password, uint32_t desired_password_length,
-            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);
-
-    /**
-     * Verifies provided_password matches enrolled_password_handle.
-     *
-     * Implementations of this module may retain the result of this call
-     * to attest to the recency of authentication.
-     *
-     * On success, writes the address of a verification token to auth_token,
-     * usable to attest password verification to other trusted services. Clients
-     * may pass NULL for this value.
-     *
-     * Returns: 0 on success or an error code less than 0 on error
-     * On error, verification token will not be allocated
-     */
-    int verify(uint32_t uid, uint64_t challenge,
-            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
-            const uint8_t *provided_password, uint32_t provided_password_length,
-            uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);
-private:
-    std::unique_ptr<SoftGateKeeper> impl_;
-};
-
-} // namespace gatekeeper
-
-#endif //SOFT_GATEKEEPER_DEVICE_H_
diff --git a/adb/daemon/remount_service.h b/gatekeeperd/binder/android/service/gatekeeper/GateKeeperResponse.aidl
similarity index 76%
rename from adb/daemon/remount_service.h
rename to gatekeeperd/binder/android/service/gatekeeper/GateKeeperResponse.aidl
index 522a5da..097bb54 100644
--- a/adb/daemon/remount_service.h
+++ b/gatekeeperd/binder/android/service/gatekeeper/GateKeeperResponse.aidl
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#pragma once
+package android.service.gatekeeper;
 
-#include <string>
+/**
+ * Response object for a GateKeeper verification request.
+ * @hide
+ */
+parcelable GateKeeperResponse cpp_header "gatekeeper/GateKeeperResponse.h";
 
-#include "adb_unique_fd.h"
-
-#if defined(__ANDROID__)
-void remount_service(unique_fd, const std::string&);
-#endif
diff --git a/gatekeeperd/binder/android/service/gatekeeper/IGateKeeperService.aidl b/gatekeeperd/binder/android/service/gatekeeper/IGateKeeperService.aidl
new file mode 100644
index 0000000..57adaba
--- /dev/null
+++ b/gatekeeperd/binder/android/service/gatekeeper/IGateKeeperService.aidl
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.gatekeeper;
+
+import android.service.gatekeeper.GateKeeperResponse;
+
+/**
+ * Interface for communication with GateKeeper, the
+ * secure password storage daemon.
+ *
+ * This must be kept manually in sync with system/core/gatekeeperd
+ * until AIDL can generate both C++ and Java bindings.
+ *
+ * @hide
+ */
+interface IGateKeeperService {
+    /**
+     * Enrolls a password, returning the handle to the enrollment to be stored locally.
+     * @param uid The Android user ID associated to this enrollment
+     * @param currentPasswordHandle The previously enrolled handle, or null if none
+     * @param currentPassword The previously enrolled plaintext password, or null if none.
+     *                        If provided, must verify against the currentPasswordHandle.
+     * @param desiredPassword The new desired password, for which a handle will be returned
+     *                        upon success.
+     * @return an EnrollResponse or null on failure
+     */
+    GateKeeperResponse enroll(int uid, in @nullable byte[] currentPasswordHandle,
+            in @nullable byte[] currentPassword, in byte[] desiredPassword);
+
+    /**
+     * Verifies an enrolled handle against a provided, plaintext blob.
+     * @param uid The Android user ID associated to this enrollment
+     * @param enrolledPasswordHandle The handle against which the provided password will be
+     *                               verified.
+     * @param The plaintext blob to verify against enrolledPassword.
+     * @return a VerifyResponse, or null on failure.
+     */
+    GateKeeperResponse verify(int uid, in byte[] enrolledPasswordHandle, in byte[] providedPassword);
+
+    /**
+     * Verifies an enrolled handle against a provided, plaintext blob.
+     * @param uid The Android user ID associated to this enrollment
+     * @param challenge a challenge to authenticate agaisnt the device credential. If successful
+     *                  authentication occurs, this value will be written to the returned
+     *                  authentication attestation.
+     * @param enrolledPasswordHandle The handle against which the provided password will be
+     *                               verified.
+     * @param The plaintext blob to verify against enrolledPassword.
+     * @return a VerifyResponse with an attestation, or null on failure.
+     */
+    GateKeeperResponse verifyChallenge(int uid, long challenge, in byte[] enrolledPasswordHandle,
+            in byte[] providedPassword);
+
+    /**
+     * Retrieves the secure identifier for the user with the provided Android ID,
+     * or 0 if none is found.
+     * @param uid the Android user id
+     */
+    long getSecureUserId(int uid);
+
+    /**
+     * Clears secure user id associated with the provided Android ID.
+     * Must be called when password is set to NONE.
+     * @param uid the Android user id.
+     */
+    void clearSecureUserId(int uid);
+
+    /**
+     * Notifies gatekeeper that device setup has been completed and any potentially still existing
+     * state from before a factory reset can be cleaned up (if it has not been already).
+     */
+    void reportDeviceSetupComplete();
+}
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 5451819..1d65b1c 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -16,7 +16,8 @@
 
 #define LOG_TAG "gatekeeperd"
 
-#include "IGateKeeperService.h"
+#include <android/service/gatekeeper/BnGateKeeperService.h>
+#include <gatekeeper/GateKeeperResponse.h>
 
 #include <errno.h>
 #include <fcntl.h>
@@ -41,8 +42,6 @@
 #include <utils/Log.h>
 #include <utils/String16.h>
 
-#include "SoftGateKeeperDevice.h"
-
 #include <hidl/HidlSupport.h>
 #include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
 
@@ -52,6 +51,11 @@
 using android::hardware::gatekeeper::V1_0::GatekeeperResponse;
 using android::hardware::Return;
 
+using ::android::binder::Status;
+using ::android::service::gatekeeper::BnGateKeeperService;
+using GKResponse = ::android::service::gatekeeper::GateKeeperResponse;
+using GKResponseCode = ::android::service::gatekeeper::ResponseCode;
+
 namespace android {
 
 static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE");
@@ -64,9 +68,8 @@
         hw_device = IGatekeeper::getService();
         is_running_gsi = android::base::GetBoolProperty(android::gsi::kGsiBootedProp, false);
 
-        if (hw_device == nullptr) {
-            ALOGW("falling back to software GateKeeper");
-            soft_device.reset(new SoftGateKeeperDevice());
+        if (!hw_device) {
+            LOG(ERROR) << "Could not find Gatekeeper device, which makes me very sad.";
         }
     }
 
@@ -92,7 +95,7 @@
 
         if (mark_cold_boot() && !is_running_gsi) {
             ALOGI("cold boot: clearing state");
-            if (hw_device != nullptr) {
+            if (hw_device) {
                 hw_device->deleteAllUsers([](const GatekeeperResponse &){});
             }
         }
@@ -154,16 +157,16 @@
         return uid;
     }
 
-    virtual int enroll(uint32_t uid,
-            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
-            const uint8_t *current_password, uint32_t current_password_length,
-            const uint8_t *desired_password, uint32_t desired_password_length,
-            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
+#define GK_ERROR *gkResponse = GKResponse::error(), Status::ok()
+
+    Status enroll(int32_t uid, const std::unique_ptr<std::vector<uint8_t>>& currentPasswordHandle,
+                  const std::unique_ptr<std::vector<uint8_t>>& currentPassword,
+                  const std::vector<uint8_t>& desiredPassword, GKResponse* gkResponse) override {
         IPCThreadState* ipc = IPCThreadState::self();
         const int calling_pid = ipc->getCallingPid();
         const int calling_uid = ipc->getCallingUid();
         if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
-            return PERMISSION_DENIED;
+            return GK_ERROR;
         }
 
         // Make sure to clear any state from before factory reset as soon as a credential is
@@ -171,226 +174,189 @@
         clear_state_if_needed();
 
         // need a desired password to enroll
-        if (desired_password_length == 0) return -EINVAL;
+        if (desiredPassword.size() == 0) return GK_ERROR;
 
-        int ret;
-        if (hw_device != nullptr) {
-            const gatekeeper::password_handle_t *handle =
-                    reinterpret_cast<const gatekeeper::password_handle_t *>(current_password_handle);
+        if (!hw_device) {
+            LOG(ERROR) << "has no HAL to talk to";
+            return GK_ERROR;
+        }
 
-            if (handle != NULL && handle->version != 0 && !handle->hardware_backed) {
-                // handle is being re-enrolled from a software version. HAL probably won't accept
-                // the handle as valid, so we nullify it and enroll from scratch
-                current_password_handle = NULL;
-                current_password_handle_length = 0;
-                current_password = NULL;
-                current_password_length = 0;
+        android::hardware::hidl_vec<uint8_t> curPwdHandle;
+        android::hardware::hidl_vec<uint8_t> curPwd;
+
+        if (currentPasswordHandle && currentPassword) {
+            if (currentPasswordHandle->size() != sizeof(gatekeeper::password_handle_t)) {
+                LOG(INFO) << "Password handle has wrong length";
+                return GK_ERROR;
             }
+            curPwdHandle.setToExternal(const_cast<uint8_t*>(currentPasswordHandle->data()),
+                                       currentPasswordHandle->size());
+            curPwd.setToExternal(const_cast<uint8_t*>(currentPassword->data()),
+                                 currentPassword->size());
+        }
 
-            android::hardware::hidl_vec<uint8_t> curPwdHandle;
-            curPwdHandle.setToExternal(const_cast<uint8_t*>(current_password_handle),
-                                       current_password_handle_length);
-            android::hardware::hidl_vec<uint8_t> curPwd;
-            curPwd.setToExternal(const_cast<uint8_t*>(current_password),
-                                 current_password_length);
-            android::hardware::hidl_vec<uint8_t> newPwd;
-            newPwd.setToExternal(const_cast<uint8_t*>(desired_password),
-                                 desired_password_length);
+        android::hardware::hidl_vec<uint8_t> newPwd;
+        newPwd.setToExternal(const_cast<uint8_t*>(desiredPassword.data()), desiredPassword.size());
 
-            uint32_t hw_uid = adjust_uid(uid);
-            Return<void> hwRes = hw_device->enroll(hw_uid, curPwdHandle, curPwd, newPwd,
-                              [&ret, enrolled_password_handle, enrolled_password_handle_length]
-                                   (const GatekeeperResponse &rsp) {
-                ret = static_cast<int>(rsp.code); // propagate errors
-                if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
-                    if (enrolled_password_handle != nullptr &&
-                        enrolled_password_handle_length != nullptr) {
-                        *enrolled_password_handle = new uint8_t[rsp.data.size()];
-                        *enrolled_password_handle_length = rsp.data.size();
-                        memcpy(*enrolled_password_handle, rsp.data.data(),
-                               *enrolled_password_handle_length);
+        uint32_t hw_uid = adjust_uid(uid);
+        Return<void> hwRes = hw_device->enroll(
+                hw_uid, curPwdHandle, curPwd, newPwd, [&gkResponse](const GatekeeperResponse& rsp) {
+                    if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
+                        *gkResponse = GKResponse::ok({rsp.data.begin(), rsp.data.end()});
+                    } else if (rsp.code == GatekeeperStatusCode::ERROR_RETRY_TIMEOUT &&
+                               rsp.timeout > 0) {
+                        *gkResponse = GKResponse::retry(rsp.timeout);
+                    } else {
+                        *gkResponse = GKResponse::error();
                     }
-                    ret = 0; // all success states are reported as 0
-                } else if (rsp.code == GatekeeperStatusCode::ERROR_RETRY_TIMEOUT && rsp.timeout > 0) {
-                    ret = rsp.timeout;
-                }
-            });
-            if (!hwRes.isOk()) {
-                ALOGE("enroll transaction failed\n");
-                ret = -1;
+                });
+        if (!hwRes.isOk()) {
+            LOG(ERROR) << "enroll transaction failed";
+            return GK_ERROR;
+        }
+
+        if (gkResponse->response_code() == GKResponseCode::OK && !gkResponse->should_reenroll()) {
+            if (gkResponse->payload().size() != sizeof(gatekeeper::password_handle_t)) {
+                LOG(ERROR) << "HAL returned password handle of invalid length "
+                           << gkResponse->payload().size();
+                return GK_ERROR;
             }
-        } else {
-            ret = soft_device->enroll(uid,
-                    current_password_handle, current_password_handle_length,
-                    current_password, current_password_length,
-                    desired_password, desired_password_length,
-                    enrolled_password_handle, enrolled_password_handle_length);
-        }
 
-        if (ret == GATEKEEPER_RESPONSE_OK && (*enrolled_password_handle == nullptr ||
-            *enrolled_password_handle_length != sizeof(password_handle_t))) {
-            ret = GATEKEEPER_RESPONSE_ERROR;
-            ALOGE("HAL: password_handle=%p size_of_handle=%" PRIu32 "\n",
-                  *enrolled_password_handle, *enrolled_password_handle_length);
-        }
-
-        if (ret == GATEKEEPER_RESPONSE_OK) {
-            gatekeeper::password_handle_t *handle =
-                    reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
+            const gatekeeper::password_handle_t* handle =
+                    reinterpret_cast<const gatekeeper::password_handle_t*>(
+                            gkResponse->payload().data());
             store_sid(uid, handle->user_id);
-            bool rr;
 
+            GKResponse verifyResponse;
             // immediately verify this password so we don't ask the user to enter it again
             // if they just created it.
-            verify(uid, *enrolled_password_handle, sizeof(password_handle_t), desired_password,
-                    desired_password_length, &rr);
+            auto status = verify(uid, gkResponse->payload(), desiredPassword, &verifyResponse);
+            if (!status.isOk() || verifyResponse.response_code() != GKResponseCode::OK) {
+                LOG(ERROR) << "Failed to verify password after enrolling";
+            }
         }
 
-        return ret;
+        return Status::ok();
     }
 
-    virtual int verify(uint32_t uid,
-            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
-            const uint8_t *provided_password, uint32_t provided_password_length, bool *request_reenroll) {
-        uint8_t *auth_token = nullptr;
-        uint32_t auth_token_length;
-        int ret = verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
-                provided_password, provided_password_length,
-                &auth_token, &auth_token_length, request_reenroll);
-        delete [] auth_token;
-        return ret;
+    Status verify(int32_t uid, const ::std::vector<uint8_t>& enrolledPasswordHandle,
+                  const ::std::vector<uint8_t>& providedPassword, GKResponse* gkResponse) override {
+        return verifyChallenge(uid, 0 /* challenge */, enrolledPasswordHandle, providedPassword,
+                               gkResponse);
     }
 
-    virtual int verifyChallenge(uint32_t uid, uint64_t challenge,
-            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
-            const uint8_t *provided_password, uint32_t provided_password_length,
-            uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
+    Status verifyChallenge(int32_t uid, int64_t challenge,
+                           const std::vector<uint8_t>& enrolledPasswordHandle,
+                           const std::vector<uint8_t>& providedPassword,
+                           GKResponse* gkResponse) override {
         IPCThreadState* ipc = IPCThreadState::self();
         const int calling_pid = ipc->getCallingPid();
         const int calling_uid = ipc->getCallingUid();
         if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
-            return PERMISSION_DENIED;
+            return GK_ERROR;
         }
 
         // can't verify if we're missing either param
-        if (enrolled_password_handle == nullptr || provided_password == nullptr ||
-            enrolled_password_handle_length == 0 || provided_password_length == 0)
-            return -EINVAL;
+        if (enrolledPasswordHandle.size() == 0 || providedPassword.size() == 0) return GK_ERROR;
 
-        int ret;
-        if (hw_device != nullptr) {
-            const gatekeeper::password_handle_t *handle =
-                    reinterpret_cast<const gatekeeper::password_handle_t *>(enrolled_password_handle);
-            // handle version 0 does not have hardware backed flag, and thus cannot be upgraded to
-            // a HAL if there was none before
-            if (handle->version == 0 || handle->hardware_backed) {
-                uint32_t hw_uid = adjust_uid(uid);
-                android::hardware::hidl_vec<uint8_t> curPwdHandle;
-                curPwdHandle.setToExternal(const_cast<uint8_t*>(enrolled_password_handle),
-                                           enrolled_password_handle_length);
-                android::hardware::hidl_vec<uint8_t> enteredPwd;
-                enteredPwd.setToExternal(const_cast<uint8_t*>(provided_password),
-                                         provided_password_length);
-                Return<void> hwRes = hw_device->verify(hw_uid, challenge, curPwdHandle, enteredPwd,
-                                        [&ret, request_reenroll, auth_token, auth_token_length]
-                                             (const GatekeeperResponse &rsp) {
-                    ret = static_cast<int>(rsp.code); // propagate errors
-                    if (auth_token != nullptr && auth_token_length != nullptr &&
-                        rsp.code >= GatekeeperStatusCode::STATUS_OK) {
-                        *auth_token = new uint8_t[rsp.data.size()];
-                        *auth_token_length = rsp.data.size();
-                        memcpy(*auth_token, rsp.data.data(), *auth_token_length);
-                        if (request_reenroll != nullptr) {
-                            *request_reenroll = (rsp.code == GatekeeperStatusCode::STATUS_REENROLL);
-                        }
-                        ret = 0; // all success states are reported as 0
-                    } else if (rsp.code == GatekeeperStatusCode::ERROR_RETRY_TIMEOUT &&
-                               rsp.timeout > 0) {
-                        ret = rsp.timeout;
+        if (!hw_device) return GK_ERROR;
+
+        if (enrolledPasswordHandle.size() != sizeof(gatekeeper::password_handle_t)) {
+            LOG(INFO) << "Password handle has wrong length";
+            return GK_ERROR;
+        }
+        const gatekeeper::password_handle_t* handle =
+                reinterpret_cast<const gatekeeper::password_handle_t*>(
+                        enrolledPasswordHandle.data());
+
+        uint32_t hw_uid = adjust_uid(uid);
+        android::hardware::hidl_vec<uint8_t> curPwdHandle;
+        curPwdHandle.setToExternal(const_cast<uint8_t*>(enrolledPasswordHandle.data()),
+                                   enrolledPasswordHandle.size());
+        android::hardware::hidl_vec<uint8_t> enteredPwd;
+        enteredPwd.setToExternal(const_cast<uint8_t*>(providedPassword.data()),
+                                 providedPassword.size());
+
+        Return<void> hwRes = hw_device->verify(
+                hw_uid, challenge, curPwdHandle, enteredPwd,
+                [&gkResponse](const GatekeeperResponse& rsp) {
+                    if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
+                        *gkResponse = GKResponse::ok(
+                                {rsp.data.begin(), rsp.data.end()},
+                                rsp.code == GatekeeperStatusCode::STATUS_REENROLL /* reenroll */);
+                    } else if (rsp.code == GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
+                        *gkResponse = GKResponse::retry(rsp.timeout);
+                    } else {
+                        *gkResponse = GKResponse::error();
                     }
                 });
-                if (!hwRes.isOk()) {
-                    ALOGE("verify transaction failed\n");
-                    ret = -1;
-                }
-            } else {
-                // upgrade scenario, a HAL has been added to this device where there was none before
-                SoftGateKeeperDevice soft_dev;
-                ret = soft_dev.verify(uid, challenge,
-                    enrolled_password_handle, enrolled_password_handle_length,
-                    provided_password, provided_password_length, auth_token, auth_token_length,
-                    request_reenroll);
 
-                if (ret == 0) {
-                    // success! re-enroll with HAL
-                    if (request_reenroll != nullptr) *request_reenroll = true;
+        if (!hwRes.isOk()) {
+            LOG(ERROR) << "verify transaction failed";
+            return GK_ERROR;
+        }
+
+        if (gkResponse->response_code() == GKResponseCode::OK) {
+            if (gkResponse->payload().size() != 0) {
+                sp<IServiceManager> sm = defaultServiceManager();
+                sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
+                sp<security::keystore::IKeystoreService> service =
+                        interface_cast<security::keystore::IKeystoreService>(binder);
+
+                if (service) {
+                    int result = 0;
+                    auto binder_result = service->addAuthToken(gkResponse->payload(), &result);
+                    if (!binder_result.isOk() ||
+                        !keystore::KeyStoreServiceReturnCode(result).isOk()) {
+                        LOG(ERROR) << "Failure sending auth token to KeyStore: " << result;
+                    }
+                } else {
+                    LOG(ERROR) << "Cannot deliver auth token. Unable to communicate with Keystore.";
                 }
             }
-        } else {
-            ret = soft_device->verify(uid, challenge,
-                enrolled_password_handle, enrolled_password_handle_length,
-                provided_password, provided_password_length, auth_token, auth_token_length,
-                request_reenroll);
+
+            maybe_store_sid(uid, handle->user_id);
         }
 
-        if (ret == 0 && *auth_token != NULL && *auth_token_length > 0) {
-            // TODO: cache service?
-            sp<IServiceManager> sm = defaultServiceManager();
-            sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
-            sp<security::keystore::IKeystoreService> service =
-                    interface_cast<security::keystore::IKeystoreService>(binder);
-            if (service != NULL) {
-                std::vector<uint8_t> auth_token_vector(*auth_token,
-                                                       (*auth_token) + *auth_token_length);
-                int result = 0;
-                auto binder_result = service->addAuthToken(auth_token_vector, &result);
-                if (!binder_result.isOk() || !keystore::KeyStoreServiceReturnCode(result).isOk()) {
-                    ALOGE("Failure sending auth token to KeyStore: %" PRId32, result);
-                }
-            } else {
-                ALOGE("Unable to communicate with KeyStore");
-            }
-        }
-
-        if (ret == 0) {
-            maybe_store_sid(uid, reinterpret_cast<const gatekeeper::password_handle_t *>(
-                        enrolled_password_handle)->user_id);
-        }
-
-        return ret;
+        return Status::ok();
     }
 
-    virtual uint64_t getSecureUserId(uint32_t uid) { return read_sid(uid); }
+    Status getSecureUserId(int32_t uid, int64_t* sid) override {
+        *sid = read_sid(uid);
+        return Status::ok();
+    }
 
-    virtual void clearSecureUserId(uint32_t uid) {
+    Status clearSecureUserId(int32_t uid) override {
         IPCThreadState* ipc = IPCThreadState::self();
         const int calling_pid = ipc->getCallingPid();
         const int calling_uid = ipc->getCallingUid();
         if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
             ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
-            return;
+            return Status::ok();
         }
         clear_sid(uid);
 
-        if (hw_device != nullptr) {
+        if (hw_device) {
             uint32_t hw_uid = adjust_uid(uid);
             hw_device->deleteUser(hw_uid, [] (const GatekeeperResponse &){});
         }
+        return Status::ok();
     }
 
-    virtual void reportDeviceSetupComplete() {
+    Status reportDeviceSetupComplete() override {
         IPCThreadState* ipc = IPCThreadState::self();
         const int calling_pid = ipc->getCallingPid();
         const int calling_uid = ipc->getCallingUid();
         if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
             ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
-            return;
+            return Status::ok();
         }
 
         clear_state_if_needed();
+        return Status::ok();
     }
 
-    virtual status_t dump(int fd, const Vector<String16> &) {
+    status_t dump(int fd, const Vector<String16>&) override {
         IPCThreadState* ipc = IPCThreadState::self();
         const int pid = ipc->getCallingPid();
         const int uid = ipc->getCallingUid();
@@ -411,7 +377,6 @@
 
 private:
     sp<IGatekeeper> hw_device;
-    std::unique_ptr<SoftGateKeeperDevice> soft_device;
 
     bool clear_state_if_needed_done;
     bool is_running_gsi;
diff --git a/gatekeeperd/include/gatekeeper/GateKeeperResponse.h b/gatekeeperd/include/gatekeeper/GateKeeperResponse.h
new file mode 100644
index 0000000..99fff02
--- /dev/null
+++ b/gatekeeperd/include/gatekeeper/GateKeeperResponse.h
@@ -0,0 +1,85 @@
+/*
+**
+** Copyright 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.
+*/
+
+#ifndef GATEKEEPERD_INCLUDE_GATEKEEPER_GATEKEEPERRESPONSE_H_
+#define GATEKEEPERD_INCLUDE_GATEKEEPER_GATEKEEPERRESPONSE_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace service {
+namespace gatekeeper {
+
+enum class ResponseCode : int32_t {
+    ERROR = -1,
+    OK = 0,
+    RETRY = 1,
+};
+
+class GateKeeperResponse : public ::android::Parcelable {
+    GateKeeperResponse(ResponseCode response_code, int32_t timeout = 0,
+                       std::vector<uint8_t> payload = {}, bool should_reenroll = false)
+        : response_code_(response_code),
+          timeout_(timeout),
+          payload_(std::move(payload)),
+          should_reenroll_(should_reenroll) {}
+
+  public:
+    GateKeeperResponse() = default;
+    GateKeeperResponse(GateKeeperResponse&&) = default;
+    GateKeeperResponse(const GateKeeperResponse&) = default;
+    GateKeeperResponse& operator=(GateKeeperResponse&&) = default;
+
+    static GateKeeperResponse error() { return GateKeeperResponse(ResponseCode::ERROR); }
+    static GateKeeperResponse retry(int32_t timeout) {
+        return GateKeeperResponse(ResponseCode::RETRY, timeout);
+    }
+    static GateKeeperResponse ok(std::vector<uint8_t> payload, bool reenroll = false) {
+        return GateKeeperResponse(ResponseCode::OK, 0, std::move(payload), reenroll);
+    }
+
+    status_t readFromParcel(const Parcel* in) override;
+    status_t writeToParcel(Parcel* out) const override;
+
+    const std::vector<uint8_t>& payload() const { return payload_; }
+
+    void payload(std::vector<uint8_t> payload) { payload_ = payload; }
+
+    ResponseCode response_code() const { return response_code_; }
+
+    void response_code(ResponseCode response_code) { response_code_ = response_code; }
+
+    bool should_reenroll() const { return should_reenroll_; }
+
+    void should_reenroll(bool should_reenroll) { should_reenroll_ = should_reenroll; }
+
+    int32_t timeout() const { return timeout_; }
+
+    void timeout(int32_t timeout) { timeout_ = timeout; }
+
+  private:
+    ResponseCode response_code_;
+    int32_t timeout_;
+    std::vector<uint8_t> payload_;
+    bool should_reenroll_;
+};
+
+}  // namespace gatekeeper
+}  // namespace service
+}  // namespace android
+
+#endif  // GATEKEEPERD_INCLUDE_GATEKEEPER_GATEKEEPERRESPONSE_H_
diff --git a/gatekeeperd/tests/Android.bp b/gatekeeperd/tests/Android.bp
deleted file mode 100644
index d4cf93b..0000000
--- a/gatekeeperd/tests/Android.bp
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (C) 2015 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_test {
-    name: "gatekeeperd-unit-tests",
-
-    cflags: [
-        "-g",
-        "-Wall",
-        "-Werror",
-        "-Wno-missing-field-initializers",
-    ],
-    shared_libs: [
-        "libgatekeeper",
-        "libcrypto",
-        "libbase",
-    ],
-    static_libs: ["libscrypt_static"],
-    include_dirs: ["external/scrypt/lib/crypto"],
-    srcs: ["gatekeeper_test.cpp"],
-}
diff --git a/gatekeeperd/tests/gatekeeper_test.cpp b/gatekeeperd/tests/gatekeeper_test.cpp
deleted file mode 100644
index 100375f..0000000
--- a/gatekeeperd/tests/gatekeeper_test.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright 2015 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 <arpa/inet.h>
-#include <iostream>
-
-#include <gtest/gtest.h>
-#include <hardware/hw_auth_token.h>
-
-#include "../SoftGateKeeper.h"
-
-using ::gatekeeper::SizedBuffer;
-using ::testing::Test;
-using ::gatekeeper::EnrollRequest;
-using ::gatekeeper::EnrollResponse;
-using ::gatekeeper::VerifyRequest;
-using ::gatekeeper::VerifyResponse;
-using ::gatekeeper::SoftGateKeeper;
-using ::gatekeeper::secure_id_t;
-
-static void do_enroll(SoftGateKeeper &gatekeeper, EnrollResponse *response) {
-    SizedBuffer password;
-
-    password.buffer.reset(new uint8_t[16]);
-    password.length = 16;
-    memset(password.buffer.get(), 0, 16);
-    EnrollRequest request(0, NULL, &password, NULL);
-
-    gatekeeper.Enroll(request, response);
-}
-
-TEST(GateKeeperTest, EnrollSuccess) {
-    SoftGateKeeper gatekeeper;
-    EnrollResponse response;
-    do_enroll(gatekeeper, &response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-}
-
-TEST(GateKeeperTest, EnrollBogusData) {
-    SoftGateKeeper gatekeeper;
-    SizedBuffer password;
-    EnrollResponse response;
-
-    EnrollRequest request(0, NULL, &password, NULL);
-
-    gatekeeper.Enroll(request, &response);
-
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
-}
-
-TEST(GateKeeperTest, VerifySuccess) {
-    SoftGateKeeper gatekeeper;
-    SizedBuffer provided_password;
-    EnrollResponse enroll_response;
-
-    provided_password.buffer.reset(new uint8_t[16]);
-    provided_password.length = 16;
-    memset(provided_password.buffer.get(), 0, 16);
-
-    do_enroll(gatekeeper, &enroll_response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-    VerifyRequest request(0, 1, &enroll_response.enrolled_password_handle,
-            &provided_password);
-    VerifyResponse response;
-
-    gatekeeper.Verify(request, &response);
-
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-
-    hw_auth_token_t *auth_token =
-        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());
-
-    ASSERT_EQ((uint32_t) HW_AUTH_PASSWORD, ntohl(auth_token->authenticator_type));
-    ASSERT_EQ((uint64_t) 1, auth_token->challenge);
-    ASSERT_NE(~((uint32_t) 0), auth_token->timestamp);
-    ASSERT_NE((uint64_t) 0, auth_token->user_id);
-    ASSERT_NE((uint64_t) 0, auth_token->authenticator_id);
-}
-
-TEST(GateKeeperTest, TrustedReEnroll) {
-    SoftGateKeeper gatekeeper;
-    SizedBuffer provided_password;
-    EnrollResponse enroll_response;
-    SizedBuffer password_handle;
-
-    // do_enroll enrolls an all 0 password
-    provided_password.buffer.reset(new uint8_t[16]);
-    provided_password.length = 16;
-    memset(provided_password.buffer.get(), 0, 16);
-    do_enroll(gatekeeper, &enroll_response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
-    // keep a copy of the handle
-    password_handle.buffer.reset(new uint8_t[enroll_response.enrolled_password_handle.length]);
-    password_handle.length = enroll_response.enrolled_password_handle.length;
-    memcpy(password_handle.buffer.get(), enroll_response.enrolled_password_handle.buffer.get(),
-            password_handle.length);
-
-    // verify first password
-    VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle,
-            &provided_password);
-    VerifyResponse response;
-    gatekeeper.Verify(request, &response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-    hw_auth_token_t *auth_token =
-        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());
-
-    secure_id_t secure_id = auth_token->user_id;
-
-    // enroll new password
-    provided_password.buffer.reset(new uint8_t[16]);
-    provided_password.length = 16;
-    memset(provided_password.buffer.get(), 0, 16);
-    SizedBuffer password;
-    password.buffer.reset(new uint8_t[16]);
-    memset(password.buffer.get(), 1, 16);
-    password.length = 16;
-    EnrollRequest enroll_request(0, &password_handle, &password, &provided_password);
-    gatekeeper.Enroll(enroll_request, &enroll_response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
-    // verify new password
-    password.buffer.reset(new uint8_t[16]);
-    memset(password.buffer.get(), 1, 16);
-    password.length = 16;
-    VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle,
-            &password);
-    gatekeeper.Verify(new_request, &response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-    ASSERT_EQ(secure_id,
-        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id);
-}
-
-
-TEST(GateKeeperTest, UntrustedReEnroll) {
-    SoftGateKeeper gatekeeper;
-    SizedBuffer provided_password;
-    EnrollResponse enroll_response;
-
-    // do_enroll enrolls an all 0 password
-    provided_password.buffer.reset(new uint8_t[16]);
-    provided_password.length = 16;
-    memset(provided_password.buffer.get(), 0, 16);
-    do_enroll(gatekeeper, &enroll_response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
-    // verify first password
-    VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle,
-            &provided_password);
-    VerifyResponse response;
-    gatekeeper.Verify(request, &response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-    hw_auth_token_t *auth_token =
-        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());
-
-    secure_id_t secure_id = auth_token->user_id;
-
-    // enroll new password
-    SizedBuffer password;
-    password.buffer.reset(new uint8_t[16]);
-    memset(password.buffer.get(), 1, 16);
-    password.length = 16;
-    EnrollRequest enroll_request(0, NULL, &password, NULL);
-    gatekeeper.Enroll(enroll_request, &enroll_response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
-    // verify new password
-    password.buffer.reset(new uint8_t[16]);
-    memset(password.buffer.get(), 1, 16);
-    password.length = 16;
-    VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle,
-            &password);
-    gatekeeper.Verify(new_request, &response);
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-    ASSERT_NE(secure_id,
-        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id);
-}
-
-
-TEST(GateKeeperTest, VerifyBogusData) {
-    SoftGateKeeper gatekeeper;
-    SizedBuffer provided_password;
-    SizedBuffer password_handle;
-    VerifyResponse response;
-
-    VerifyRequest request(0, 0, &provided_password, &password_handle);
-
-    gatekeeper.Verify(request, &response);
-
-    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
-}
diff --git a/healthd/Android.bp b/healthd/Android.bp
index 2cf6be9..14d46b3 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -17,6 +17,10 @@
     shared_libs: [
         "libutils",
         "libbase",
+
+        // Need latest HealthInfo definition from headers of this shared
+        // library. Clients don't need to link to this.
+        "android.hardware.health@2.1",
     ],
     header_libs: ["libhealthd_headers"],
     export_header_lib_headers: ["libhealthd_headers"],
@@ -42,8 +46,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
         "android.hardware.health@2.0",
@@ -87,6 +89,7 @@
 
 cc_library_static {
     name: "libhealthd_charger_nops",
+    recovery_available: true,
 
     srcs: [
         "healthd_mode_charger_nops.cpp",
@@ -102,11 +105,138 @@
     ],
 
     static_libs: [
-        "android.hardware.health@2.0-impl",
+        "libhealthloop",
+        "libhealth2impl",
     ],
 
     shared_libs: [
-        "android.hardware.health@2.0",
+        "android.hardware.health@2.1",
         "libutils",
     ],
 }
+
+sysprop_library {
+    name: "charger_sysprop",
+    recovery_available: true,
+    srcs: ["charger.sysprop"],
+    property_owner: "Platform",
+    api_packages: ["android.sysprop"],
+}
+
+cc_library_static {
+    name: "libhealthd_draw",
+    export_include_dirs: ["."],
+    static_libs: [
+        "libcharger_sysprop",
+        "libminui",
+    ],
+    shared_libs: [
+        "libbase",
+    ],
+    header_libs: ["libbatteryservice_headers"],
+
+    srcs: ["healthd_draw.cpp"],
+}
+
+cc_library_static {
+    name: "libhealthd_charger",
+    local_include_dirs: ["include"],
+    export_include_dirs: [".", "include"],
+
+    static_libs: [
+        "android.hardware.health@1.0-convert",
+        "libcharger_sysprop",
+        "libhealthd_draw",
+        "libhealthloop",
+        "libhealth2impl",
+        "libminui",
+    ],
+
+    shared_libs: [
+        "android.hardware.health@2.1",
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libpng",
+        "libsuspend",
+        "libutils",
+    ],
+
+    srcs: [
+        "healthd_mode_charger.cpp",
+        "AnimationParser.cpp",
+    ],
+}
+
+cc_defaults {
+    name: "charger_defaults",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        // common
+        "android.hardware.health@2.0",
+        "android.hardware.health@2.1",
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+
+        // system charger only
+        "libpng",
+    ],
+
+    static_libs: [
+        // common
+        "android.hardware.health@1.0-convert",
+        "libbatterymonitor",
+        "libcharger_sysprop",
+        "libhealthd_charger_nops",
+        "libhealthloop",
+        "libhealth2impl",
+
+        // system charger only
+        "libhealthd_draw",
+        "libhealthd_charger",
+        "libminui",
+        "libsuspend",
+    ],
+}
+
+cc_binary {
+    name: "charger",
+    defaults: ["charger_defaults"],
+    recovery_available: true,
+    srcs: [
+        "charger.cpp",
+        "charger_utils.cpp",
+    ],
+
+    target: {
+        recovery: {
+            // No UI and libsuspend for recovery charger.
+            cflags: [
+                "-DCHARGER_FORCE_NO_UI=1",
+            ],
+            exclude_shared_libs: [
+                "libpng",
+            ],
+            exclude_static_libs: [
+                "libhealthd_draw",
+                "libhealthd_charger",
+                "libminui",
+                "libsuspend",
+            ],
+        }
+    }
+}
+
+cc_test {
+    name: "charger_test",
+    defaults: ["charger_defaults"],
+    srcs: ["charger_test.cpp"],
+}
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 05123af..4b09cf8 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -2,189 +2,10 @@
 
 LOCAL_PATH := $(call my-dir)
 
-### libhealthd_draw ###
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libhealthd_draw
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-LOCAL_STATIC_LIBRARIES := libminui
-LOCAL_SHARED_LIBRARIES := libbase
-LOCAL_SRC_FILES := healthd_draw.cpp
-
-ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_SCREEN),)
-LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=$(TARGET_HEALTHD_DRAW_SPLIT_SCREEN)
-else
-LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_SCREEN=0
-endif
-
-ifneq ($(TARGET_HEALTHD_DRAW_SPLIT_OFFSET),)
-LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=$(TARGET_HEALTHD_DRAW_SPLIT_OFFSET)
-else
-LOCAL_CFLAGS += -DHEALTHD_DRAW_SPLIT_OFFSET=0
-endif
-
-LOCAL_HEADER_LIBRARIES := libbatteryservice_headers
-
-include $(BUILD_STATIC_LIBRARY)
-
-### libhealthd_charger ###
-include $(CLEAR_VARS)
-
-LOCAL_CFLAGS := -Werror
-ifeq ($(strip $(BOARD_CHARGER_DISABLE_INIT_BLANK)),true)
-LOCAL_CFLAGS += -DCHARGER_DISABLE_INIT_BLANK
-endif
-ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
-LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND
-endif
-
-LOCAL_SRC_FILES := \
-    healthd_mode_charger.cpp \
-    AnimationParser.cpp
-
-LOCAL_MODULE := libhealthd_charger
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH) \
-    $(LOCAL_PATH)/include
-
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.health@2.0-impl \
-    android.hardware.health@1.0-convert \
-    libhealthstoragedefault \
-    libhealthd_draw \
-    libminui \
-
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.health@2.0 \
-    libbase \
-    libcutils \
-    liblog \
-    libpng \
-    libutils \
-
-ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
-LOCAL_SHARED_LIBRARIES += libsuspend
-endif
-
-include $(BUILD_STATIC_LIBRARY)
-
-### charger ###
-include $(CLEAR_VARS)
 ifeq ($(strip $(BOARD_CHARGER_NO_UI)),true)
 LOCAL_CHARGER_NO_UI := true
 endif
 
-LOCAL_SRC_FILES := \
-    charger.cpp \
-
-LOCAL_MODULE := charger
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-
-LOCAL_CFLAGS := -Werror
-ifeq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
-LOCAL_CFLAGS += -DCHARGER_NO_UI
-endif
-
-CHARGER_STATIC_LIBRARIES := \
-    android.hardware.health@2.0-impl \
-    android.hardware.health@1.0-convert \
-    libbinderthreadstate \
-    libhidltransport \
-    libhidlbase \
-    libhealthstoragedefault \
-    libvndksupport \
-    libhealthd_charger \
-    libhealthd_charger_nops \
-    libhealthd_draw \
-    libbatterymonitor \
-
-CHARGER_SHARED_LIBRARIES := \
-    android.hardware.health@2.0 \
-    libbase \
-    libcutils \
-    libjsoncpp \
-    libprocessgroup \
-    liblog \
-    libutils \
-
-ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
-CHARGER_STATIC_LIBRARIES += libminui
-CHARGER_SHARED_LIBRARIES += libpng
-endif
-
-ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
-CHARGER_SHARED_LIBRARIES += libsuspend
-endif
-
-LOCAL_STATIC_LIBRARIES := $(CHARGER_STATIC_LIBRARIES)
-LOCAL_SHARED_LIBRARIES := $(CHARGER_SHARED_LIBRARIES)
-
-LOCAL_HAL_STATIC_LIBRARIES := libhealthd
-
-# Symlink /charger to /system/bin/charger
-LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT) \
-    && ln -sf /system/bin/charger $(TARGET_ROOT_OUT)/charger
-
-include $(BUILD_EXECUTABLE)
-
-### charger.recovery ###
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    charger.cpp \
-
-LOCAL_MODULE := charger.recovery
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/bin
-LOCAL_MODULE_STEM := charger
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_CFLAGS += -DCHARGER_NO_UI
-
-# charger.recovery doesn't link against libhealthd_{charger,draw} or libminui, since it doesn't need
-# any UI support.
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.health@2.0-impl \
-    android.hardware.health@1.0-convert \
-    libbinderthreadstate \
-    libhidltransport \
-    libhidlbase \
-    libhealthstoragedefault \
-    libvndksupport \
-    libhealthd_charger_nops \
-    libbatterymonitor \
-
-# These shared libs will be installed to recovery image because of the dependency in `recovery`
-# module.
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.health@2.0 \
-    libbase \
-    libcutils \
-    liblog \
-    libutils \
-
-# The use of LOCAL_HAL_STATIC_LIBRARIES prevents from building this module with Android.bp.
-LOCAL_HAL_STATIC_LIBRARIES := libhealthd
-
-include $(BUILD_EXECUTABLE)
-
-### charger_test ###
-include $(CLEAR_VARS)
-LOCAL_MODULE := charger_test
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Wall -Werror -DCHARGER_NO_UI
-LOCAL_STATIC_LIBRARIES := $(CHARGER_STATIC_LIBRARIES)
-LOCAL_SHARED_LIBRARIES := $(CHARGER_SHARED_LIBRARIES)
-LOCAL_SRC_FILES := \
-    charger_test.cpp \
-
-include $(BUILD_EXECUTABLE)
-
-CHARGER_STATIC_LIBRARIES :=
-CHARGER_SHARED_LIBRARIES :=
-
 ### charger_res_images ###
 ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
 define _add-charger-image
diff --git a/healthd/AnimationParser.cpp b/healthd/AnimationParser.cpp
index 864038b..fde3b95 100644
--- a/healthd/AnimationParser.cpp
+++ b/healthd/AnimationParser.cpp
@@ -84,7 +84,6 @@
     static constexpr const char* fail_prefix = "fail: ";
     static constexpr const char* clock_prefix = "clock_display: ";
     static constexpr const char* percent_prefix = "percent_display: ";
-    static constexpr const char* frame_prefix = "frame: ";
 
     std::vector<animation::frame> frames;
 
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 06c8176..bdf4aac 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -29,10 +29,12 @@
 
 #include <algorithm>
 #include <memory>
+#include <optional>
 
 #include <android-base/file.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
+#include <android/hardware/health/2.1/types.h>
 #include <batteryservice/BatteryService.h>
 #include <cutils/klog.h>
 #include <cutils/properties.h>
@@ -47,97 +49,106 @@
 #define MILLION 1.0e6
 #define DEFAULT_VBUS_VOLTAGE 5000000
 
+using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
+using HealthInfo_2_0 = android::hardware::health::V2_0::HealthInfo;
+using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V1_0::BatteryHealth;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V2_1::BatteryCapacityLevel;
+
 namespace android {
 
-struct sysfsStringEnumMap {
+template <typename T>
+struct SysfsStringEnumMap {
     const char* s;
-    int val;
+    T val;
 };
 
-static int mapSysfsString(const char* str,
-                          struct sysfsStringEnumMap map[]) {
+template <typename T>
+static std::optional<T> mapSysfsString(const char* str, SysfsStringEnumMap<T> map[]) {
     for (int i = 0; map[i].s; i++)
         if (!strcmp(str, map[i].s))
             return map[i].val;
 
-    return -1;
+    return std::nullopt;
 }
 
-static void initBatteryProperties(BatteryProperties* props) {
-    props->chargerAcOnline = false;
-    props->chargerUsbOnline = false;
-    props->chargerWirelessOnline = false;
-    props->maxChargingCurrent = 0;
-    props->maxChargingVoltage = 0;
-    props->batteryStatus = BATTERY_STATUS_UNKNOWN;
-    props->batteryHealth = BATTERY_HEALTH_UNKNOWN;
-    props->batteryPresent = false;
-    props->batteryLevel = 0;
-    props->batteryVoltage = 0;
-    props->batteryTemperature = 0;
-    props->batteryCurrent = 0;
-    props->batteryCycleCount = 0;
-    props->batteryFullCharge = 0;
-    props->batteryChargeCounter = 0;
-    props->batteryTechnology.clear();
+static void initHealthInfo(HealthInfo_2_1* health_info_2_1) {
+    *health_info_2_1 = HealthInfo_2_1{};
+
+    // HIDL enum values are zero initialized, so they need to be initialized
+    // properly.
+    health_info_2_1->batteryCapacityLevel = BatteryCapacityLevel::UNKNOWN;
+    auto* props = &health_info_2_1->legacy.legacy;
+    props->batteryStatus = BatteryStatus::UNKNOWN;
+    props->batteryHealth = BatteryHealth::UNKNOWN;
 }
 
 BatteryMonitor::BatteryMonitor()
     : mHealthdConfig(nullptr),
       mBatteryDevicePresent(false),
       mBatteryFixedCapacity(0),
-      mBatteryFixedTemperature(0) {
-    initBatteryProperties(&props);
+      mBatteryFixedTemperature(0),
+      mHealthInfo(std::make_unique<HealthInfo_2_1>()) {
+    initHealthInfo(mHealthInfo.get());
 }
 
-struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor) {
-    return batteryMonitor->props;
+BatteryMonitor::~BatteryMonitor() {}
+
+const HealthInfo_1_0& BatteryMonitor::getHealthInfo_1_0() const {
+    return getHealthInfo_2_0().legacy;
 }
 
-int BatteryMonitor::getBatteryStatus(const char* status) {
-    int ret;
-    struct sysfsStringEnumMap batteryStatusMap[] = {
-        { "Unknown", BATTERY_STATUS_UNKNOWN },
-        { "Charging", BATTERY_STATUS_CHARGING },
-        { "Discharging", BATTERY_STATUS_DISCHARGING },
-        { "Not charging", BATTERY_STATUS_NOT_CHARGING },
-        { "Full", BATTERY_STATUS_FULL },
-        { NULL, 0 },
+const HealthInfo_2_0& BatteryMonitor::getHealthInfo_2_0() const {
+    return getHealthInfo_2_1().legacy;
+}
+
+const HealthInfo_2_1& BatteryMonitor::getHealthInfo_2_1() const {
+    return *mHealthInfo;
+}
+
+BatteryStatus getBatteryStatus(const char* status) {
+    static SysfsStringEnumMap<BatteryStatus> batteryStatusMap[] = {
+            {"Unknown", BatteryStatus::UNKNOWN},
+            {"Charging", BatteryStatus::CHARGING},
+            {"Discharging", BatteryStatus::DISCHARGING},
+            {"Not charging", BatteryStatus::NOT_CHARGING},
+            {"Full", BatteryStatus::FULL},
+            {NULL, BatteryStatus::UNKNOWN},
     };
 
-    ret = mapSysfsString(status, batteryStatusMap);
-    if (ret < 0) {
+    auto ret = mapSysfsString(status, batteryStatusMap);
+    if (!ret) {
         KLOG_WARNING(LOG_TAG, "Unknown battery status '%s'\n", status);
-        ret = BATTERY_STATUS_UNKNOWN;
+        *ret = BatteryStatus::UNKNOWN;
     }
 
-    return ret;
+    return *ret;
 }
 
-int BatteryMonitor::getBatteryHealth(const char* status) {
-    int ret;
-    struct sysfsStringEnumMap batteryHealthMap[] = {
-        { "Unknown", BATTERY_HEALTH_UNKNOWN },
-        { "Good", BATTERY_HEALTH_GOOD },
-        { "Overheat", BATTERY_HEALTH_OVERHEAT },
-        { "Dead", BATTERY_HEALTH_DEAD },
-        { "Over voltage", BATTERY_HEALTH_OVER_VOLTAGE },
-        { "Unspecified failure", BATTERY_HEALTH_UNSPECIFIED_FAILURE },
-        { "Cold", BATTERY_HEALTH_COLD },
-        // battery health values from JEITA spec
-        { "Warm", BATTERY_HEALTH_GOOD },
-        { "Cool", BATTERY_HEALTH_GOOD },
-        { "Hot", BATTERY_HEALTH_OVERHEAT },
-        { NULL, 0 },
+BatteryHealth getBatteryHealth(const char* status) {
+    static SysfsStringEnumMap<BatteryHealth> batteryHealthMap[] = {
+            {"Unknown", BatteryHealth::UNKNOWN},
+            {"Good", BatteryHealth::GOOD},
+            {"Overheat", BatteryHealth::OVERHEAT},
+            {"Dead", BatteryHealth::DEAD},
+            {"Over voltage", BatteryHealth::OVER_VOLTAGE},
+            {"Unspecified failure", BatteryHealth::UNSPECIFIED_FAILURE},
+            {"Cold", BatteryHealth::COLD},
+            // battery health values from JEITA spec
+            {"Warm", BatteryHealth::GOOD},
+            {"Cool", BatteryHealth::GOOD},
+            {"Hot", BatteryHealth::OVERHEAT},
+            {NULL, BatteryHealth::UNKNOWN},
     };
 
-    ret = mapSysfsString(status, batteryHealthMap);
-    if (ret < 0) {
+    auto ret = mapSysfsString(status, batteryHealthMap);
+    if (!ret) {
         KLOG_WARNING(LOG_TAG, "Unknown battery health '%s'\n", status);
-        ret = BATTERY_HEALTH_UNKNOWN;
+        *ret = BatteryHealth::UNKNOWN;
     }
 
-    return ret;
+    return *ret;
 }
 
 int BatteryMonitor::readFromFile(const String8& path, std::string* buf) {
@@ -148,35 +159,34 @@
 }
 
 BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
-    std::string buf;
-    int ret;
-    struct sysfsStringEnumMap supplyTypeMap[] = {
-            { "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
-            { "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
-            { "UPS", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "Mains", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB", ANDROID_POWER_SUPPLY_TYPE_USB },
-            { "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC },
-            { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB },
-            { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
-            { NULL, 0 },
+    static SysfsStringEnumMap<int> supplyTypeMap[] = {
+            {"Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN},
+            {"Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY},
+            {"UPS", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"Mains", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB", ANDROID_POWER_SUPPLY_TYPE_USB},
+            {"USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_C", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC},
+            {"USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB},
+            {"Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS},
+            {NULL, 0},
     };
+    std::string buf;
 
     if (readFromFile(path, &buf) <= 0)
         return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
 
-    ret = mapSysfsString(buf.c_str(), supplyTypeMap);
-    if (ret < 0) {
+    auto ret = mapSysfsString(buf.c_str(), supplyTypeMap);
+    if (!ret) {
         KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
-        ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
+        *ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
     }
 
-    return static_cast<BatteryMonitor::PowerSupplyType>(ret);
+    return static_cast<BatteryMonitor::PowerSupplyType>(*ret);
 }
 
 bool BatteryMonitor::getBooleanField(const String8& path) {
@@ -200,10 +210,10 @@
     return value;
 }
 
-bool BatteryMonitor::update(void) {
-    bool logthis;
+void BatteryMonitor::updateValues(void) {
+    initHealthInfo(mHealthInfo.get());
 
-    initBatteryProperties(&props);
+    HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
 
     if (!mHealthdConfig->batteryPresentPath.isEmpty())
         props.batteryPresent = getBooleanField(mHealthdConfig->batteryPresentPath);
@@ -227,6 +237,15 @@
     if (!mHealthdConfig->batteryChargeCounterPath.isEmpty())
         props.batteryChargeCounter = getIntField(mHealthdConfig->batteryChargeCounterPath);
 
+    if (!mHealthdConfig->batteryCurrentAvgPath.isEmpty())
+        mHealthInfo->legacy.batteryCurrentAverage =
+                getIntField(mHealthdConfig->batteryCurrentAvgPath);
+
+    // TODO(b/142260281): Retrieve these values correctly.
+    mHealthInfo->batteryCapacityLevel = BatteryCapacityLevel::UNKNOWN;
+    mHealthInfo->batteryChargeTimeToFullNowSeconds = 0;
+    mHealthInfo->batteryFullCapacityUah = props.batteryFullCharge;
+
     props.batteryTemperature = mBatteryFixedTemperature ?
         mBatteryFixedTemperature :
         getIntField(mHealthdConfig->batteryTemperaturePath);
@@ -289,62 +308,58 @@
             }
         }
     }
+}
 
-    logthis = !healthd_board_battery_update(&props);
+void BatteryMonitor::logValues(void) {
+    char dmesgline[256];
+    size_t len;
+    const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
+    if (props.batteryPresent) {
+        snprintf(dmesgline, sizeof(dmesgline), "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
+                 props.batteryLevel, props.batteryVoltage, props.batteryTemperature < 0 ? "-" : "",
+                 abs(props.batteryTemperature / 10), abs(props.batteryTemperature % 10),
+                 props.batteryHealth, props.batteryStatus);
 
-    if (logthis) {
-        char dmesgline[256];
-        size_t len;
-        if (props.batteryPresent) {
-            snprintf(dmesgline, sizeof(dmesgline),
-                 "battery l=%d v=%d t=%s%d.%d h=%d st=%d",
-                 props.batteryLevel, props.batteryVoltage,
-                 props.batteryTemperature < 0 ? "-" : "",
-                 abs(props.batteryTemperature / 10),
-                 abs(props.batteryTemperature % 10), props.batteryHealth,
-                 props.batteryStatus);
-
-            len = strlen(dmesgline);
-            if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
-                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
-                                " c=%d", props.batteryCurrent);
-            }
-
-            if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
-                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
-                                " fc=%d", props.batteryFullCharge);
-            }
-
-            if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
-                len += snprintf(dmesgline + len, sizeof(dmesgline) - len,
-                                " cc=%d", props.batteryCycleCount);
-            }
-        } else {
-            len = snprintf(dmesgline, sizeof(dmesgline),
-                 "battery none");
+        len = strlen(dmesgline);
+        if (!mHealthdConfig->batteryCurrentNowPath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " c=%d",
+                            props.batteryCurrent);
         }
 
-        snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
-                 props.chargerAcOnline ? "a" : "",
-                 props.chargerUsbOnline ? "u" : "",
-                 props.chargerWirelessOnline ? "w" : "");
+        if (!mHealthdConfig->batteryFullChargePath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " fc=%d",
+                            props.batteryFullCharge);
+        }
 
-        KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
+        if (!mHealthdConfig->batteryCycleCountPath.isEmpty()) {
+            len += snprintf(dmesgline + len, sizeof(dmesgline) - len, " cc=%d",
+                            props.batteryCycleCount);
+        }
+    } else {
+        len = snprintf(dmesgline, sizeof(dmesgline), "battery none");
     }
 
-    healthd_mode_ops->battery_update(&props);
+    snprintf(dmesgline + len, sizeof(dmesgline) - len, " chg=%s%s%s",
+             props.chargerAcOnline ? "a" : "", props.chargerUsbOnline ? "u" : "",
+             props.chargerWirelessOnline ? "w" : "");
+
+    KLOG_WARNING(LOG_TAG, "%s\n", dmesgline);
+}
+
+bool BatteryMonitor::isChargerOnline() {
+    const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
     return props.chargerAcOnline | props.chargerUsbOnline |
             props.chargerWirelessOnline;
 }
 
 int BatteryMonitor::getChargeStatus() {
-    int result = BATTERY_STATUS_UNKNOWN;
+    BatteryStatus result = BatteryStatus::UNKNOWN;
     if (!mHealthdConfig->batteryStatusPath.isEmpty()) {
         std::string buf;
         if (readFromFile(mHealthdConfig->batteryStatusPath, &buf) > 0)
             result = getBatteryStatus(buf.c_str());
     }
-    return result;
+    return static_cast<int>(result);
 }
 
 status_t BatteryMonitor::getProperty(int id, struct BatteryProperty *val) {
@@ -417,6 +432,7 @@
 void BatteryMonitor::dumpState(int fd) {
     int v;
     char vs[128];
+    const HealthInfo_1_0& props = mHealthInfo->legacy.legacy;
 
     snprintf(vs, sizeof(vs), "ac: %d usb: %d wireless: %d current_max: %d voltage_max: %d\n",
              props.chargerAcOnline, props.chargerUsbOnline,
diff --git a/healthd/animation.h b/healthd/animation.h
index 9476c91..d02d7a7 100644
--- a/healthd/animation.h
+++ b/healthd/animation.h
@@ -75,7 +75,7 @@
 
     bool run;
 
-    frame* frames;
+    frame* frames = nullptr;
     int cur_frame;
     int num_frames;
     int first_frame_repeats;  // Number of times to repeat the first frame in the current cycle
@@ -85,6 +85,8 @@
 
     int cur_level;  // current battery level being animated (0-100)
     int cur_status;  // current battery status - see BatteryService.h for BATTERY_STATUS_*
+
+    ~animation() { delete frames; }
 };
 
 }
diff --git a/healthd/api/charger_sysprop-current.txt b/healthd/api/charger_sysprop-current.txt
new file mode 100644
index 0000000..678c847
--- /dev/null
+++ b/healthd/api/charger_sysprop-current.txt
@@ -0,0 +1,29 @@
+props {
+  module: "android.sysprop.ChargerProperties"
+  prop {
+    api_name: "disable_init_blank"
+    scope: Internal
+    prop_name: "ro.charger.disable_init_blank"
+  }
+  prop {
+    api_name: "draw_split_offset"
+    type: Long
+    scope: Internal
+    prop_name: "ro.charger.draw_split_offset"
+  }
+  prop {
+    api_name: "draw_split_screen"
+    scope: Internal
+    prop_name: "ro.charger.draw_split_screen"
+  }
+  prop {
+    api_name: "enable_suspend"
+    scope: Internal
+    prop_name: "ro.charger.enable_suspend"
+  }
+  prop {
+    api_name: "no_ui"
+    scope: Internal
+    prop_name: "ro.charger.no_ui"
+  }
+}
diff --git a/healthd/api/charger_sysprop-latest.txt b/healthd/api/charger_sysprop-latest.txt
new file mode 100644
index 0000000..678c847
--- /dev/null
+++ b/healthd/api/charger_sysprop-latest.txt
@@ -0,0 +1,29 @@
+props {
+  module: "android.sysprop.ChargerProperties"
+  prop {
+    api_name: "disable_init_blank"
+    scope: Internal
+    prop_name: "ro.charger.disable_init_blank"
+  }
+  prop {
+    api_name: "draw_split_offset"
+    type: Long
+    scope: Internal
+    prop_name: "ro.charger.draw_split_offset"
+  }
+  prop {
+    api_name: "draw_split_screen"
+    scope: Internal
+    prop_name: "ro.charger.draw_split_screen"
+  }
+  prop {
+    api_name: "enable_suspend"
+    scope: Internal
+    prop_name: "ro.charger.enable_suspend"
+  }
+  prop {
+    api_name: "no_ui"
+    scope: Internal
+    prop_name: "ro.charger.no_ui"
+  }
+}
diff --git a/healthd/charger.cpp b/healthd/charger.cpp
index 085cceb..58ed416 100644
--- a/healthd/charger.cpp
+++ b/healthd/charger.cpp
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
+#include "charger.sysprop.h"
 #include "healthd_mode_charger.h"
 #include "healthd_mode_charger_nops.h"
 
-int main(int argc, char** argv) {
-#ifdef CHARGER_NO_UI
-    return healthd_charger_nops(argc, argv);
-#else
-    return healthd_charger_main(argc, argv);
+#ifndef CHARGER_FORCE_NO_UI
+#define CHARGER_FORCE_NO_UI 0
 #endif
+
+int main(int argc, char** argv) {
+    if (CHARGER_FORCE_NO_UI || android::sysprop::ChargerProperties::no_ui().value_or(false)) {
+        return healthd_charger_nops(argc, argv);
+    } else {
+        return healthd_charger_main(argc, argv);
+    }
 }
diff --git a/healthd/charger.sysprop b/healthd/charger.sysprop
new file mode 100644
index 0000000..b3f47a1
--- /dev/null
+++ b/healthd/charger.sysprop
@@ -0,0 +1,38 @@
+owner: Platform
+module: "android.sysprop.ChargerProperties"
+
+prop {
+    api_name: "draw_split_screen"
+    type: Boolean
+    prop_name: "ro.charger.draw_split_screen"
+    scope: Internal
+    access: Readonly
+}
+prop {
+    api_name: "draw_split_offset"
+    type: Long
+    prop_name: "ro.charger.draw_split_offset"
+    scope: Internal
+    access: Readonly
+}
+prop {
+    api_name: "disable_init_blank"
+    type: Boolean
+    prop_name: "ro.charger.disable_init_blank"
+    scope: Internal
+    access: Readonly
+}
+prop {
+    api_name: "enable_suspend"
+    type: Boolean
+    prop_name: "ro.charger.enable_suspend"
+    scope: Internal
+    access: Readonly
+}
+prop {
+    api_name: "no_ui"
+    type: Boolean
+    prop_name: "ro.charger.no_ui"
+    scope: Internal
+    access: Readonly
+}
diff --git a/healthd/charger_test.cpp b/healthd/charger_test.cpp
index a7e2161..e0bde68 100644
--- a/healthd/charger_test.cpp
+++ b/healthd/charger_test.cpp
@@ -21,13 +21,22 @@
 #include <condition_variable>
 #include <fstream>
 #include <iostream>
+#include <memory>
 #include <mutex>
 #include <streambuf>
 #include <string>
 #include <thread>
 #include <vector>
 
-#include <health2/Health.h>
+#include <health/utils.h>
+#include <health2impl/Health.h>
+
+#include "healthd_mode_charger.h"
+
+using android::hardware::health::InitHealthdConfig;
+using android::hardware::health::V2_1::HealthInfo;
+using android::hardware::health::V2_1::IHealth;
+using android::hardware::health::V2_1::implementation::Health;
 
 #define LOG_THIS(fmt, ...)     \
     ALOGE(fmt, ##__VA_ARGS__); \
@@ -129,22 +138,23 @@
     config->screen_on = NULL;
 }
 
-int healthd_board_battery_update(struct android::BatteryProperties*) {
-    getUpdateNotifier().set(true /* updated */);
+class TestHealth : public Health {
+  protected:
+    using Health::Health;
+    void UpdateHealthInfo(HealthInfo*) override { getUpdateNotifier().set(true /* updated */); }
+};
 
-    // return 0 to log periodic polled battery status to kernel log
-    return 0;
-}
-
-extern int healthd_charger_main(int argc, char** argv);
-
-int main(int argc, char** argv) {
-    using android::hardware::health::V2_0::implementation::Health;
-
+int main(int /*argc*/, char** /*argv*/) {
     const char* dumpFile = "/data/local/tmp/dump.txt";
 
+    auto config = std::make_unique<healthd_config>();
+    InitHealthdConfig(config.get());
+    healthd_board_init(config.get());
+    sp<IHealth> passthrough = new TestHealth(std::move(config));
+
     std::thread bgThread([=] {
-        healthd_charger_main(argc, argv);
+        android::Charger charger(passthrough);
+        charger.StartLoop();
     });
 
     // wait for healthd_init to finish
@@ -153,7 +163,7 @@
         exit(1);
     }
 
-    Health::getImplementation()->debug(createHidlHandle(dumpFile), {} /* options */);
+    passthrough->debug(createHidlHandle(dumpFile), {} /* options */);
 
     std::string content = openToString(dumpFile);
     int status = expectContains(content, {
diff --git a/healthd/charger_utils.cpp b/healthd/charger_utils.cpp
new file mode 100644
index 0000000..0cf9df5
--- /dev/null
+++ b/healthd/charger_utils.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "charger_utils.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <health/utils.h>
+#include <health2impl/Health.h>
+#include <hidl/ServiceManagement.h>
+
+using android::hardware::getPassthroughServiceManager;
+using android::hidl::base::V1_0::IBase;
+using android::hidl::manager::V1_0::IServiceManager;
+
+namespace android {
+namespace hardware {
+namespace health {
+sp<V2_1::IHealth> GetPassthroughHealthImpl() {
+    // Not using getService() because there is no hwservicemanager in charger mode.
+    sp<IServiceManager> pm = getPassthroughServiceManager();
+    if (pm == nullptr) {
+        LOG(WARNING) << "Cannot get passthrough service manager.";
+        return nullptr;
+    }
+    sp<IBase> base = pm->get(V2_0::IHealth::descriptor, "default");
+    if (base == nullptr) {
+        LOG(WARNING) << "Cannot find passthrough implementation of health 2.0 HAL for instance "
+                        "'default' on the device.";
+        return nullptr;
+    }
+    sp<V2_1::IHealth> service = V2_1::IHealth::castFrom(base);
+    if (service == nullptr) {
+        LOG(WARNING)
+                << "Cannot cast passthrough implementation of health 2.0 HAL to 2.1 for instance "
+                   "'default' on the device.";
+        return nullptr;
+    }
+    return service;
+}
+
+sp<V2_1::IHealth> GetPassthroughHealth() {
+    auto impl = GetPassthroughHealthImpl();
+    if (impl == nullptr) {
+        LOG(WARNING) << "Charger uses system defaults.";
+        auto config = std::make_unique<healthd_config>();
+        InitHealthdConfig(config.get());
+        impl = new V2_1::implementation::Health(std::move(config));
+    }
+    return impl;
+}
+
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
diff --git a/init/boringssl_self_test.h b/healthd/charger_utils.h
similarity index 72%
copy from init/boringssl_self_test.h
copy to healthd/charger_utils.h
index b21fc78..f96e827 100644
--- a/init/boringssl_self_test.h
+++ b/healthd/charger_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -16,13 +16,12 @@
 
 #pragma once
 
-#include "builtin_arguments.h"
-#include "result.h"
+#include <android/hardware/health/2.1/IHealth.h>
 
 namespace android {
-namespace init {
-
-Result<Success> StartBoringSslSelfTest(const BuiltinArguments&);
-
-}  // namespace init
+namespace hardware {
+namespace health {
+sp<V2_1::IHealth> GetPassthroughHealth();
+}  // namespace health
+}  // namespace hardware
 }  // namespace android
diff --git a/healthd/healthd_draw.cpp b/healthd/healthd_draw.cpp
index 3da8bda..50eee19 100644
--- a/healthd/healthd_draw.cpp
+++ b/healthd/healthd_draw.cpp
@@ -18,15 +18,34 @@
 #include <batteryservice/BatteryService.h>
 #include <cutils/klog.h>
 
+#include "charger.sysprop.h"
 #include "healthd_draw.h"
 
 #define LOGE(x...) KLOG_ERROR("charger", x);
 #define LOGW(x...) KLOG_WARNING("charger", x);
 #define LOGV(x...) KLOG_DEBUG("charger", x);
 
+static bool get_split_screen() {
+    return android::sysprop::ChargerProperties::draw_split_screen().value_or(false);
+}
+
+static int get_split_offset() {
+    int64_t value = android::sysprop::ChargerProperties::draw_split_offset().value_or(0);
+    if (value < static_cast<int64_t>(std::numeric_limits<int>::min())) {
+        LOGW("draw_split_offset = %" PRId64 " overflow for an int; resetting to %d.\n", value,
+             std::numeric_limits<int>::min());
+        value = std::numeric_limits<int>::min();
+    }
+    if (value > static_cast<int64_t>(std::numeric_limits<int>::max())) {
+        LOGW("draw_split_offset = %" PRId64 " overflow for an int; resetting to %d.\n", value,
+             std::numeric_limits<int>::max());
+        value = std::numeric_limits<int>::max();
+    }
+    return static_cast<int>(value);
+}
+
 HealthdDraw::HealthdDraw(animation* anim)
-  : kSplitScreen(HEALTHD_DRAW_SPLIT_SCREEN),
-    kSplitOffset(HEALTHD_DRAW_SPLIT_OFFSET) {
+    : kSplitScreen(get_split_screen()), kSplitOffset(get_split_offset()) {
     int ret = gr_init();
 
     if (ret < 0) {
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 0e5aa4f..7d844c9 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "healthd_mode_charger.h"
+
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -28,7 +30,7 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <functional>
+#include <optional>
 
 #include <android-base/file.h>
 #include <android-base/macros.h>
@@ -43,21 +45,34 @@
 #include <cutils/uevent.h>
 #include <sys/reboot.h>
 
-#ifdef CHARGER_ENABLE_SUSPEND
 #include <suspend/autosuspend.h>
-#endif
 
 #include "AnimationParser.h"
+#include "charger.sysprop.h"
+#include "charger_utils.h"
 #include "healthd_draw.h"
 
-#include <health2/Health.h>
+#include <android/hardware/health/2.0/IHealthInfoCallback.h>
+#include <health/utils.h>
+#include <health2impl/HalHealthLoop.h>
+#include <health2impl/Health.h>
 #include <healthd/healthd.h>
 
 using namespace android;
+using android::hardware::Return;
+using android::hardware::health::GetPassthroughHealth;
+using android::hardware::health::HealthLoop;
+using android::hardware::health::V1_0::BatteryStatus;
+using android::hardware::health::V2_0::Result;
+using android::hardware::health::V2_1::IHealth;
+using IHealth_2_0 = android::hardware::health::V2_0::IHealth;
+using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
+using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
 
 // main healthd loop
 extern int healthd_main(void);
 
+// minui globals
 char* locale;
 
 #ifndef max
@@ -78,6 +93,7 @@
 #define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
 #define UNPLUGGED_DISPLAY_TIME (3 * MSEC_PER_SEC)
 #define MAX_BATT_LEVEL_WAIT_TIME (3 * MSEC_PER_SEC)
+#define UNPLUGGED_SHUTDOWN_TIME_PROP "ro.product.charger.unplugged_shutdown_time"
 
 #define LAST_KMSG_MAX_SZ (32 * 1024)
 
@@ -85,6 +101,8 @@
 #define LOGW(x...) KLOG_WARNING("charger", x);
 #define LOGV(x...) KLOG_DEBUG("charger", x);
 
+namespace android {
+
 // 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.
@@ -93,28 +111,6 @@
 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;
-    bool down;
-    int64_t timestamp;
-};
-
-struct charger {
-    bool have_battery_state;
-    bool charger_connected;
-    bool screen_blanked;
-    int64_t next_screen_transition;
-    int64_t next_key_check;
-    int64_t next_pwr_check;
-    int64_t wait_batt_level_timestamp;
-
-    key_state keys[KEY_MAX + 1];
-
-    animation* batt_anim;
-    GRSurface* surf_unknown;
-    int boot_min_cap;
-};
-
 static const animation BASE_ANIMATION = {
     .text_clock =
         {
@@ -153,51 +149,51 @@
     .cur_status = BATTERY_STATUS_UNKNOWN,
 };
 
-static animation::frame default_animation_frames[] = {
-    {
-        .disp_time = 750,
-        .min_level = 0,
-        .max_level = 19,
-        .surface = NULL,
-    },
-    {
-        .disp_time = 750,
-        .min_level = 0,
-        .max_level = 39,
-        .surface = NULL,
-    },
-    {
-        .disp_time = 750,
-        .min_level = 0,
-        .max_level = 59,
-        .surface = NULL,
-    },
-    {
-        .disp_time = 750,
-        .min_level = 0,
-        .max_level = 79,
-        .surface = NULL,
-    },
-    {
-        .disp_time = 750,
-        .min_level = 80,
-        .max_level = 95,
-        .surface = NULL,
-    },
-    {
-        .disp_time = 750,
-        .min_level = 0,
-        .max_level = 100,
-        .surface = NULL,
-    },
-};
+void Charger::InitDefaultAnimationFrames() {
+    owned_frames_ = {
+            {
+                    .disp_time = 750,
+                    .min_level = 0,
+                    .max_level = 19,
+                    .surface = NULL,
+            },
+            {
+                    .disp_time = 750,
+                    .min_level = 0,
+                    .max_level = 39,
+                    .surface = NULL,
+            },
+            {
+                    .disp_time = 750,
+                    .min_level = 0,
+                    .max_level = 59,
+                    .surface = NULL,
+            },
+            {
+                    .disp_time = 750,
+                    .min_level = 0,
+                    .max_level = 79,
+                    .surface = NULL,
+            },
+            {
+                    .disp_time = 750,
+                    .min_level = 80,
+                    .max_level = 95,
+                    .surface = NULL,
+            },
+            {
+                    .disp_time = 750,
+                    .min_level = 0,
+                    .max_level = 100,
+                    .surface = NULL,
+            },
+    };
+}
 
-static animation battery_animation = BASE_ANIMATION;
+Charger::Charger(const sp<IHealth>& service)
+    : HalHealthLoop("charger", service), batt_anim_(BASE_ANIMATION) {}
 
-static charger charger_state;
-static healthd_config* healthd_config;
-static android::BatteryProperties* batt_prop;
-static std::unique_ptr<HealthdDraw> healthd_draw;
+Charger::~Charger() {}
 
 /* current time in milliseconds */
 static int64_t curr_time_ms() {
@@ -263,18 +259,16 @@
     LOGW("\n");
 }
 
-#ifdef CHARGER_ENABLE_SUSPEND
 static int request_suspend(bool enable) {
+    if (!android::sysprop::ChargerProperties::enable_suspend().value_or(false)) {
+        return 0;
+    }
+
     if (enable)
         return autosuspend_enable();
     else
         return autosuspend_disable();
 }
-#else
-static int request_suspend(bool /*enable*/) {
-    return 0;
-}
-#endif
 
 static void kick_animation(animation* anim) {
     anim->run = true;
@@ -286,123 +280,125 @@
     anim->run = false;
 }
 
-static void update_screen_state(charger* charger, int64_t now) {
-    animation* batt_anim = charger->batt_anim;
+void Charger::UpdateScreenState(int64_t now) {
     int disp_time;
 
-    if (!batt_anim->run || now < charger->next_screen_transition) return;
+    if (!batt_anim_.run || now < next_screen_transition_) return;
 
     // If battery level is not ready, keep checking in the defined time
-    if (batt_prop == nullptr ||
-        (batt_prop->batteryLevel == 0 && batt_prop->batteryStatus == BATTERY_STATUS_UNKNOWN)) {
-        if (charger->wait_batt_level_timestamp == 0) {
+    if (health_info_.batteryLevel == 0 && health_info_.batteryStatus == BatteryStatus::UNKNOWN) {
+        if (wait_batt_level_timestamp_ == 0) {
             // Set max delay time and skip drawing screen
-            charger->wait_batt_level_timestamp = now + MAX_BATT_LEVEL_WAIT_TIME;
+            wait_batt_level_timestamp_ = now + MAX_BATT_LEVEL_WAIT_TIME;
             LOGV("[%" PRId64 "] wait for battery capacity ready\n", now);
             return;
-        } else if (now <= charger->wait_batt_level_timestamp) {
+        } else if (now <= wait_batt_level_timestamp_) {
             // Do nothing, keep waiting
             return;
         }
         // If timeout and battery level is still not ready, draw unknown battery
     }
 
-    if (healthd_draw == nullptr) {
-        if (healthd_config && healthd_config->screen_on) {
-            if (!healthd_config->screen_on(batt_prop)) {
+    if (healthd_draw_ == nullptr) {
+        std::optional<bool> out_screen_on;
+        service()->shouldKeepScreenOn([&](Result res, bool screen_on) {
+            if (res == Result::SUCCESS) {
+                *out_screen_on = screen_on;
+            }
+        });
+        if (out_screen_on.has_value()) {
+            if (!*out_screen_on) {
                 LOGV("[%" PRId64 "] leave screen off\n", now);
-                batt_anim->run = false;
-                charger->next_screen_transition = -1;
-                if (charger->charger_connected) request_suspend(true);
+                batt_anim_.run = false;
+                next_screen_transition_ = -1;
+                if (charger_online()) request_suspend(true);
                 return;
             }
         }
 
-        healthd_draw.reset(new HealthdDraw(batt_anim));
+        healthd_draw_.reset(new HealthdDraw(&batt_anim_));
 
-#ifndef CHARGER_DISABLE_INIT_BLANK
-        healthd_draw->blank_screen(true);
-        charger->screen_blanked = true;
-#endif
+        if (android::sysprop::ChargerProperties::disable_init_blank().value_or(false)) {
+            healthd_draw_->blank_screen(true);
+            screen_blanked_ = true;
+        }
     }
 
     /* animation is over, blank screen and leave */
-    if (batt_anim->num_cycles > 0 && batt_anim->cur_cycle == batt_anim->num_cycles) {
-        reset_animation(batt_anim);
-        charger->next_screen_transition = -1;
-        healthd_draw->blank_screen(true);
-        charger->screen_blanked = true;
+    if (batt_anim_.num_cycles > 0 && batt_anim_.cur_cycle == batt_anim_.num_cycles) {
+        reset_animation(&batt_anim_);
+        next_screen_transition_ = -1;
+        healthd_draw_->blank_screen(true);
+        screen_blanked_ = true;
         LOGV("[%" PRId64 "] animation done\n", now);
-        if (charger->charger_connected) request_suspend(true);
+        if (charger_online()) request_suspend(true);
         return;
     }
 
-    disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time;
+    disp_time = batt_anim_.frames[batt_anim_.cur_frame].disp_time;
 
-    if (charger->screen_blanked) {
-        healthd_draw->blank_screen(false);
-        charger->screen_blanked = false;
+    if (screen_blanked_) {
+        healthd_draw_->blank_screen(false);
+        screen_blanked_ = false;
     }
 
     /* animation starting, set up the animation */
-    if (batt_anim->cur_frame == 0) {
+    if (batt_anim_.cur_frame == 0) {
         LOGV("[%" PRId64 "] animation starting\n", now);
-        if (batt_prop) {
-            batt_anim->cur_level = batt_prop->batteryLevel;
-            batt_anim->cur_status = batt_prop->batteryStatus;
-            if (batt_prop->batteryLevel >= 0 && batt_anim->num_frames != 0) {
-                /* find first frame given current battery level */
-                for (int i = 0; i < batt_anim->num_frames; i++) {
-                    if (batt_anim->cur_level >= batt_anim->frames[i].min_level &&
-                        batt_anim->cur_level <= batt_anim->frames[i].max_level) {
-                        batt_anim->cur_frame = i;
-                        break;
-                    }
+        batt_anim_.cur_level = health_info_.batteryLevel;
+        batt_anim_.cur_status = (int)health_info_.batteryStatus;
+        if (health_info_.batteryLevel >= 0 && batt_anim_.num_frames != 0) {
+            /* find first frame given current battery level */
+            for (int i = 0; i < batt_anim_.num_frames; i++) {
+                if (batt_anim_.cur_level >= batt_anim_.frames[i].min_level &&
+                    batt_anim_.cur_level <= batt_anim_.frames[i].max_level) {
+                    batt_anim_.cur_frame = i;
+                    break;
                 }
-
-                if (charger->charger_connected) {
-                    // repeat the first frame first_frame_repeats times
-                    disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time *
-                                batt_anim->first_frame_repeats;
-                } else {
-                    disp_time = UNPLUGGED_DISPLAY_TIME / batt_anim->num_cycles;
-                }
-
-                LOGV("cur_frame=%d disp_time=%d\n", batt_anim->cur_frame, disp_time);
             }
+
+            if (charger_online()) {
+                // repeat the first frame first_frame_repeats times
+                disp_time = batt_anim_.frames[batt_anim_.cur_frame].disp_time *
+                            batt_anim_.first_frame_repeats;
+            } else {
+                disp_time = UNPLUGGED_DISPLAY_TIME / batt_anim_.num_cycles;
+            }
+
+            LOGV("cur_frame=%d disp_time=%d\n", batt_anim_.cur_frame, disp_time);
         }
     }
 
     /* draw the new frame (@ cur_frame) */
-    healthd_draw->redraw_screen(charger->batt_anim, charger->surf_unknown);
+    healthd_draw_->redraw_screen(&batt_anim_, surf_unknown_);
 
     /* if we don't have anim frames, we only have one image, so just bump
      * the cycle counter and exit
      */
-    if (batt_anim->num_frames == 0 || batt_anim->cur_level < 0) {
+    if (batt_anim_.num_frames == 0 || batt_anim_.cur_level < 0) {
         LOGW("[%" PRId64 "] animation missing or unknown battery status\n", now);
-        charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;
-        batt_anim->cur_cycle++;
+        next_screen_transition_ = now + BATTERY_UNKNOWN_TIME;
+        batt_anim_.cur_cycle++;
         return;
     }
 
     /* schedule next screen transition */
-    charger->next_screen_transition = curr_time_ms() + disp_time;
+    next_screen_transition_ = curr_time_ms() + disp_time;
 
     /* advance frame cntr to the next valid frame only if we are charging
      * if necessary, advance cycle cntr, and reset frame cntr
      */
-    if (charger->charger_connected) {
-        batt_anim->cur_frame++;
+    if (charger_online()) {
+        batt_anim_.cur_frame++;
 
-        while (batt_anim->cur_frame < batt_anim->num_frames &&
-               (batt_anim->cur_level < batt_anim->frames[batt_anim->cur_frame].min_level ||
-                batt_anim->cur_level > batt_anim->frames[batt_anim->cur_frame].max_level)) {
-            batt_anim->cur_frame++;
+        while (batt_anim_.cur_frame < batt_anim_.num_frames &&
+               (batt_anim_.cur_level < batt_anim_.frames[batt_anim_.cur_frame].min_level ||
+                batt_anim_.cur_level > batt_anim_.frames[batt_anim_.cur_frame].max_level)) {
+            batt_anim_.cur_frame++;
         }
-        if (batt_anim->cur_frame >= batt_anim->num_frames) {
-            batt_anim->cur_cycle++;
-            batt_anim->cur_frame = 0;
+        if (batt_anim_.cur_frame >= batt_anim_.num_frames) {
+            batt_anim_.cur_cycle++;
+            batt_anim_.cur_frame = 0;
 
             /* don't reset the cycle counter, since we use that as a signal
              * in a test above to check if animation is over
@@ -413,29 +409,29 @@
          * If we stop it immediately instead of going through this loop, then
          * the animation would stop somewhere in the middle.
          */
-        batt_anim->cur_frame = 0;
-        batt_anim->cur_cycle++;
+        batt_anim_.cur_frame = 0;
+        batt_anim_.cur_cycle++;
     }
 }
 
-static int set_key_callback(charger* charger, int code, int value) {
+int Charger::SetKeyCallback(int code, int value) {
     int64_t now = curr_time_ms();
     int down = !!value;
 
     if (code > KEY_MAX) return -1;
 
     /* ignore events that don't modify our state */
-    if (charger->keys[code].down == down) return 0;
+    if (keys_[code].down == down) return 0;
 
     /* only record the down even timestamp, as the amount
      * of time the key spent not being pressed is not useful */
-    if (down) charger->keys[code].timestamp = now;
-    charger->keys[code].down = down;
-    charger->keys[code].pending = true;
+    if (down) keys_[code].timestamp = now;
+    keys_[code].down = down;
+    keys_[code].pending = true;
     if (down) {
         LOGV("[%" PRId64 "] key[%d] down\n", now, code);
     } else {
-        int64_t duration = now - charger->keys[code].timestamp;
+        int64_t duration = now - keys_[code].timestamp;
         int64_t secs = duration / 1000;
         int64_t msecs = duration - secs * 1000;
         LOGV("[%" PRId64 "] key[%d] up (was down for %" PRId64 ".%" PRId64 "sec)\n", now, code,
@@ -445,20 +441,19 @@
     return 0;
 }
 
-static void update_input_state(charger* charger, input_event* ev) {
+void Charger::UpdateInputState(input_event* ev) {
     if (ev->type != EV_KEY) return;
-    set_key_callback(charger, ev->code, ev->value);
+    SetKeyCallback(ev->code, ev->value);
 }
 
-static void set_next_key_check(charger* charger, key_state* key, int64_t timeout) {
+void Charger::SetNextKeyCheck(key_state* key, int64_t timeout) {
     int64_t then = key->timestamp + timeout;
 
-    if (charger->next_key_check == -1 || then < charger->next_key_check)
-        charger->next_key_check = then;
+    if (next_key_check_ == -1 || then < next_key_check_) next_key_check_ = then;
 }
 
-static void process_key(charger* charger, int code, int64_t now) {
-    key_state* key = &charger->keys[code];
+void Charger::ProcessKey(int code, int64_t now) {
+    key_state* key = &keys_[code];
 
     if (code == KEY_POWER) {
         if (key->down) {
@@ -471,7 +466,7 @@
                     LOGW("[%" PRId64 "] booting from charger mode\n", now);
                     property_set("sys.boot_from_charger_mode", "1");
                 } else {
-                    if (charger->batt_anim->cur_level >= charger->boot_min_cap) {
+                    if (batt_anim_.cur_level >= boot_min_cap_) {
                         LOGW("[%" PRId64 "] rebooting\n", now);
                         reboot(RB_AUTOBOOT);
                     } else {
@@ -485,18 +480,18 @@
                 /* if the key is pressed but timeout hasn't expired,
                  * make sure we wake up at the right-ish time to check
                  */
-                set_next_key_check(charger, key, POWER_ON_KEY_TIME);
+                SetNextKeyCheck(key, POWER_ON_KEY_TIME);
 
                 /* Turn on the display and kick animation on power-key press
                  * rather than on key release
                  */
-                kick_animation(charger->batt_anim);
+                kick_animation(&batt_anim_);
                 request_suspend(false);
             }
         } else {
             /* if the power key got released, force screen state cycle */
             if (key->pending) {
-                kick_animation(charger->batt_anim);
+                kick_animation(&batt_anim_);
                 request_suspend(false);
             }
         }
@@ -505,33 +500,35 @@
     key->pending = false;
 }
 
-static void handle_input_state(charger* charger, int64_t now) {
-    process_key(charger, KEY_POWER, now);
+void Charger::HandleInputState(int64_t now) {
+    ProcessKey(KEY_POWER, now);
 
-    if (charger->next_key_check != -1 && now > charger->next_key_check)
-        charger->next_key_check = -1;
+    if (next_key_check_ != -1 && now > next_key_check_) next_key_check_ = -1;
 }
 
-static void handle_power_supply_state(charger* charger, int64_t now) {
-    if (!charger->have_battery_state) return;
+void Charger::HandlePowerSupplyState(int64_t now) {
+    int timer_shutdown = UNPLUGGED_SHUTDOWN_TIME;
+    if (!have_battery_state_) return;
 
-    if (!charger->charger_connected) {
+    if (!charger_online()) {
         request_suspend(false);
-        if (charger->next_pwr_check == -1) {
+        if (next_pwr_check_ == -1) {
             /* Last cycle would have stopped at the extreme top of battery-icon
              * Need to show the correct level corresponding to capacity.
              *
-             * Reset next_screen_transition to update screen immediately.
+             * Reset next_screen_transition_ to update screen immediately.
              * Reset & kick animation to show complete animation cycles
              * when charger disconnected.
              */
-            charger->next_screen_transition = now - 1;
-            reset_animation(charger->batt_anim);
-            kick_animation(charger->batt_anim);
-            charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME;
+            timer_shutdown =
+                    property_get_int32(UNPLUGGED_SHUTDOWN_TIME_PROP, UNPLUGGED_SHUTDOWN_TIME);
+            next_screen_transition_ = now - 1;
+            reset_animation(&batt_anim_);
+            kick_animation(&batt_anim_);
+            next_pwr_check_ = now + timer_shutdown;
             LOGW("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n",
-                 now, (int64_t)UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check);
-        } else if (now >= charger->next_pwr_check) {
+                 now, (int64_t)timer_shutdown, next_pwr_check_);
+        } else if (now >= next_pwr_check_) {
             LOGW("[%" PRId64 "] shutting down\n", now);
             reboot(RB_POWER_OFF);
         } else {
@@ -539,64 +536,60 @@
         }
     } else {
         /* online supply present, reset shutdown timer if set */
-        if (charger->next_pwr_check != -1) {
-            /* Reset next_screen_transition to update screen immediately.
+        if (next_pwr_check_ != -1) {
+            /* Reset next_screen_transition_ to update screen immediately.
              * Reset & kick animation to show complete animation cycles
              * when charger connected again.
              */
             request_suspend(false);
-            charger->next_screen_transition = now - 1;
-            reset_animation(charger->batt_anim);
-            kick_animation(charger->batt_anim);
+            next_screen_transition_ = now - 1;
+            reset_animation(&batt_anim_);
+            kick_animation(&batt_anim_);
             LOGW("[%" PRId64 "] device plugged in: shutdown cancelled\n", now);
         }
-        charger->next_pwr_check = -1;
+        next_pwr_check_ = -1;
     }
 }
 
-void healthd_mode_charger_heartbeat() {
-    charger* charger = &charger_state;
+void Charger::Heartbeat() {
+    // charger* charger = &charger_state;
     int64_t now = curr_time_ms();
 
-    handle_input_state(charger, now);
-    handle_power_supply_state(charger, now);
+    HandleInputState(now);
+    HandlePowerSupplyState(now);
 
     /* do screen update last in case any of the above want to start
      * screen transitions (animations, etc)
      */
-    update_screen_state(charger, now);
+    UpdateScreenState(now);
 }
 
-void healthd_mode_charger_battery_update(android::BatteryProperties* props) {
-    charger* charger = &charger_state;
+void Charger::OnHealthInfoChanged(const HealthInfo_2_1& health_info) {
+    set_charger_online(health_info);
 
-    charger->charger_connected =
-        props->chargerAcOnline || props->chargerUsbOnline || props->chargerWirelessOnline;
-
-    if (!charger->have_battery_state) {
-        charger->have_battery_state = true;
-        charger->next_screen_transition = curr_time_ms() - 1;
+    if (!have_battery_state_) {
+        have_battery_state_ = true;
+        next_screen_transition_ = curr_time_ms() - 1;
         request_suspend(false);
-        reset_animation(charger->batt_anim);
-        kick_animation(charger->batt_anim);
+        reset_animation(&batt_anim_);
+        kick_animation(&batt_anim_);
     }
-    batt_prop = props;
+    health_info_ = health_info.legacy.legacy;
+
+    AdjustWakealarmPeriods(charger_online());
 }
 
-int healthd_mode_charger_preparetowait(void) {
-    charger* charger = &charger_state;
+int Charger::PrepareToWait(void) {
     int64_t now = curr_time_ms();
     int64_t next_event = INT64_MAX;
     int64_t timeout;
 
     LOGV("[%" PRId64 "] next screen: %" PRId64 " next key: %" PRId64 " next pwr: %" PRId64 "\n",
-         now, charger->next_screen_transition, charger->next_key_check, charger->next_pwr_check);
+         now, next_screen_transition_, next_key_check_, next_pwr_check_);
 
-    if (charger->next_screen_transition != -1) next_event = charger->next_screen_transition;
-    if (charger->next_key_check != -1 && charger->next_key_check < next_event)
-        next_event = charger->next_key_check;
-    if (charger->next_pwr_check != -1 && charger->next_pwr_check < next_event)
-        next_event = charger->next_pwr_check;
+    if (next_screen_transition_ != -1) next_event = next_screen_transition_;
+    if (next_key_check_ != -1 && next_key_check_ < next_event) next_event = next_key_check_;
+    if (next_pwr_check_ != -1 && next_pwr_check_ < next_event) next_event = next_pwr_check_;
 
     if (next_event != -1 && next_event != INT64_MAX)
         timeout = max(0, next_event - now);
@@ -606,32 +599,32 @@
     return (int)timeout;
 }
 
-static int input_callback(charger* charger, int fd, unsigned int epevents) {
+int Charger::InputCallback(int fd, unsigned int epevents) {
     input_event ev;
     int ret;
 
     ret = ev_get_input(fd, epevents, &ev);
     if (ret) return -1;
-    update_input_state(charger, &ev);
+    UpdateInputState(&ev);
     return 0;
 }
 
-static void charger_event_handler(uint32_t /*epevents*/) {
+static void charger_event_handler(HealthLoop* /*charger_loop*/, uint32_t /*epevents*/) {
     int ret;
 
     ret = ev_wait(-1);
     if (!ret) ev_dispatch();
 }
 
-animation* init_animation() {
+void Charger::InitAnimation() {
     bool parse_success;
 
     std::string 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);
+        parse_success = parse_animation_desc(content, &batt_anim_);
+        batt_anim_.set_resource_root(product_animation_root);
     } else if (base::ReadFileToString(animation_desc_path, &content)) {
-        parse_success = parse_animation_desc(content, &battery_animation);
+        parse_success = parse_animation_desc(content, &batt_anim_);
     } else {
         LOGW("Could not open animation description at %s\n", animation_desc_path);
         parse_success = false;
@@ -639,41 +632,36 @@
 
     if (!parse_success) {
         LOGW("Could not parse animation description. Using default animation.\n");
-        battery_animation = BASE_ANIMATION;
-        battery_animation.animation_file.assign("charger/battery_scale");
-        battery_animation.frames = default_animation_frames;
-        battery_animation.num_frames = ARRAY_SIZE(default_animation_frames);
+        batt_anim_ = BASE_ANIMATION;
+        batt_anim_.animation_file.assign("charger/battery_scale");
+        InitDefaultAnimationFrames();
+        batt_anim_.frames = owned_frames_.data();
+        batt_anim_.num_frames = owned_frames_.size();
     }
-    if (battery_animation.fail_file.empty()) {
-        battery_animation.fail_file.assign("charger/battery_fail");
+    if (batt_anim_.fail_file.empty()) {
+        batt_anim_.fail_file.assign("charger/battery_fail");
     }
 
     LOGV("Animation Description:\n");
-    LOGV("  animation: %d %d '%s' (%d)\n", battery_animation.num_cycles,
-         battery_animation.first_frame_repeats, battery_animation.animation_file.c_str(),
-         battery_animation.num_frames);
-    LOGV("  fail_file: '%s'\n", battery_animation.fail_file.c_str());
-    LOGV("  clock: %d %d %d %d %d %d '%s'\n", battery_animation.text_clock.pos_x,
-         battery_animation.text_clock.pos_y, battery_animation.text_clock.color_r,
-         battery_animation.text_clock.color_g, battery_animation.text_clock.color_b,
-         battery_animation.text_clock.color_a, battery_animation.text_clock.font_file.c_str());
-    LOGV("  percent: %d %d %d %d %d %d '%s'\n", battery_animation.text_percent.pos_x,
-         battery_animation.text_percent.pos_y, battery_animation.text_percent.color_r,
-         battery_animation.text_percent.color_g, battery_animation.text_percent.color_b,
-         battery_animation.text_percent.color_a, battery_animation.text_percent.font_file.c_str());
-    for (int i = 0; i < battery_animation.num_frames; i++) {
-        LOGV("  frame %.2d: %d %d %d\n", i, battery_animation.frames[i].disp_time,
-             battery_animation.frames[i].min_level, battery_animation.frames[i].max_level);
+    LOGV("  animation: %d %d '%s' (%d)\n", batt_anim_.num_cycles, batt_anim_.first_frame_repeats,
+         batt_anim_.animation_file.c_str(), batt_anim_.num_frames);
+    LOGV("  fail_file: '%s'\n", batt_anim_.fail_file.c_str());
+    LOGV("  clock: %d %d %d %d %d %d '%s'\n", batt_anim_.text_clock.pos_x,
+         batt_anim_.text_clock.pos_y, batt_anim_.text_clock.color_r, batt_anim_.text_clock.color_g,
+         batt_anim_.text_clock.color_b, batt_anim_.text_clock.color_a,
+         batt_anim_.text_clock.font_file.c_str());
+    LOGV("  percent: %d %d %d %d %d %d '%s'\n", batt_anim_.text_percent.pos_x,
+         batt_anim_.text_percent.pos_y, batt_anim_.text_percent.color_r,
+         batt_anim_.text_percent.color_g, batt_anim_.text_percent.color_b,
+         batt_anim_.text_percent.color_a, batt_anim_.text_percent.font_file.c_str());
+    for (int i = 0; i < batt_anim_.num_frames; i++) {
+        LOGV("  frame %.2d: %d %d %d\n", i, batt_anim_.frames[i].disp_time,
+             batt_anim_.frames[i].min_level, batt_anim_.frames[i].max_level);
     }
-
-    return &battery_animation;
 }
 
-void healthd_mode_charger_init(struct healthd_config* config) {
-    using android::hardware::health::V2_0::implementation::Health;
-
+void Charger::Init(struct healthd_config* config) {
     int ret;
-    charger* charger = &charger_state;
     int i;
     int epollfd;
 
@@ -681,22 +669,22 @@
 
     LOGW("--------------- STARTING CHARGER MODE ---------------\n");
 
-    ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1, std::placeholders::_2));
+    ret = ev_init(
+            std::bind(&Charger::InputCallback, this, std::placeholders::_1, std::placeholders::_2));
     if (!ret) {
         epollfd = ev_get_epollfd();
-        healthd_register_event(epollfd, charger_event_handler, EVENT_WAKEUP_FD);
+        RegisterEvent(epollfd, &charger_event_handler, EVENT_WAKEUP_FD);
     }
 
-    animation* anim = init_animation();
-    charger->batt_anim = anim;
+    InitAnimation();
 
-    ret = res_create_display_surface(anim->fail_file.c_str(), &charger->surf_unknown);
+    ret = res_create_display_surface(batt_anim_.fail_file.c_str(), &surf_unknown_);
     if (ret < 0) {
         LOGE("Cannot load custom battery_fail image. Reverting to built in: %d\n", ret);
-        ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
+        ret = res_create_display_surface("charger/battery_fail", &surf_unknown_);
         if (ret < 0) {
             LOGE("Cannot load built in battery_fail image\n");
-            charger->surf_unknown = NULL;
+            surf_unknown_ = NULL;
         }
     }
 
@@ -704,49 +692,41 @@
     int scale_count;
     int scale_fps;  // Not in use (charger/battery_scale doesn't have FPS text
                     // chunk). We are using hard-coded frame.disp_time instead.
-    ret = res_create_multi_display_surface(anim->animation_file.c_str(), &scale_count, &scale_fps,
-                                           &scale_frames);
+    ret = res_create_multi_display_surface(batt_anim_.animation_file.c_str(), &scale_count,
+                                           &scale_fps, &scale_frames);
     if (ret < 0) {
         LOGE("Cannot load battery_scale image\n");
-        anim->num_frames = 0;
-        anim->num_cycles = 1;
-    } else if (scale_count != anim->num_frames) {
+        batt_anim_.num_frames = 0;
+        batt_anim_.num_cycles = 1;
+    } else if (scale_count != batt_anim_.num_frames) {
         LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n", scale_count,
-             anim->num_frames);
-        anim->num_frames = 0;
-        anim->num_cycles = 1;
+             batt_anim_.num_frames);
+        batt_anim_.num_frames = 0;
+        batt_anim_.num_cycles = 1;
     } else {
-        for (i = 0; i < anim->num_frames; i++) {
-            anim->frames[i].surface = scale_frames[i];
+        for (i = 0; i < batt_anim_.num_frames; i++) {
+            batt_anim_.frames[i].surface = scale_frames[i];
         }
     }
-    ev_sync_key_state(
-        std::bind(&set_key_callback, charger, std::placeholders::_1, std::placeholders::_2));
+    ev_sync_key_state(std::bind(&Charger::SetKeyCallback, this, std::placeholders::_1,
+                                std::placeholders::_2));
 
-    charger->next_screen_transition = -1;
-    charger->next_key_check = -1;
-    charger->next_pwr_check = -1;
-    charger->wait_batt_level_timestamp = 0;
+    next_screen_transition_ = -1;
+    next_key_check_ = -1;
+    next_pwr_check_ = -1;
+    wait_batt_level_timestamp_ = 0;
 
-    // Initialize Health implementation (which initializes the internal BatteryMonitor).
-    Health::initInstance(config);
+    // Retrieve healthd_config from the existing health HAL.
+    HalHealthLoop::Init(config);
 
-    healthd_config = config;
-    charger->boot_min_cap = config->boot_min_cap;
+    boot_min_cap_ = config->boot_min_cap;
 }
 
-static struct healthd_mode_ops charger_ops = {
-        .init = healthd_mode_charger_init,
-        .preparetowait = healthd_mode_charger_preparetowait,
-        .heartbeat = healthd_mode_charger_heartbeat,
-        .battery_update = healthd_mode_charger_battery_update,
-};
+}  // namespace android
 
 int healthd_charger_main(int argc, char** argv) {
     int ch;
 
-    healthd_mode_ops = &charger_ops;
-
     while ((ch = getopt(argc, argv, "cr")) != -1) {
         switch (ch) {
             case 'c':
@@ -762,5 +742,6 @@
         }
     }
 
-    return healthd_main();
+    Charger charger(GetPassthroughHealth());
+    return charger.StartLoop();
 }
diff --git a/healthd/healthd_mode_charger.h b/healthd/healthd_mode_charger.h
index 2f0c9f2..370ca86 100644
--- a/healthd/healthd_mode_charger.h
+++ b/healthd/healthd_mode_charger.h
@@ -16,4 +16,72 @@
 
 #pragma once
 
+#include <linux/input.h>
+
+#include <memory>
+#include <vector>
+
+#include <android/hardware/health/2.0/IHealthInfoCallback.h>
+#include <android/hardware/health/2.1/IHealth.h>
+#include <health2impl/HalHealthLoop.h>
+
+#include "animation.h"
+
+class GRSurface;
+class HealthdDraw;
+
+namespace android {
+struct key_state {
+    bool pending;
+    bool down;
+    int64_t timestamp;
+};
+
+class Charger : public ::android::hardware::health::V2_1::implementation::HalHealthLoop {
+  public:
+    using HealthInfo_1_0 = android::hardware::health::V1_0::HealthInfo;
+    using HealthInfo_2_1 = android::hardware::health::V2_1::HealthInfo;
+
+    Charger(const sp<android::hardware::health::V2_1::IHealth>& service);
+    ~Charger();
+
+  protected:
+    // HealthLoop overrides.
+    void Heartbeat() override;
+    int PrepareToWait() override;
+    void Init(struct healthd_config* config) override;
+    // HalHealthLoop overrides
+    void OnHealthInfoChanged(const HealthInfo_2_1& health_info) override;
+
+  private:
+    void InitDefaultAnimationFrames();
+    void UpdateScreenState(int64_t now);
+    int SetKeyCallback(int code, int value);
+    void UpdateInputState(input_event* ev);
+    void SetNextKeyCheck(key_state* key, int64_t timeout);
+    void ProcessKey(int code, int64_t now);
+    void HandleInputState(int64_t now);
+    void HandlePowerSupplyState(int64_t now);
+    int InputCallback(int fd, unsigned int epevents);
+    void InitAnimation();
+
+    bool have_battery_state_ = false;
+    bool screen_blanked_ = false;
+    int64_t next_screen_transition_ = 0;
+    int64_t next_key_check_ = 0;
+    int64_t next_pwr_check_ = 0;
+    int64_t wait_batt_level_timestamp_ = 0;
+
+    key_state keys_[KEY_MAX + 1];
+
+    animation batt_anim_;
+    GRSurface* surf_unknown_ = nullptr;
+    int boot_min_cap_ = 0;
+
+    HealthInfo_1_0 health_info_ = {};
+    std::unique_ptr<HealthdDraw> healthd_draw_;
+    std::vector<animation::frame> owned_frames_;
+};
+}  // namespace android
+
 int healthd_charger_main(int argc, char** argv);
diff --git a/healthd/healthd_mode_charger_nops.cpp b/healthd/healthd_mode_charger_nops.cpp
index bcc04d5..13e7348 100644
--- a/healthd/healthd_mode_charger_nops.cpp
+++ b/healthd/healthd_mode_charger_nops.cpp
@@ -16,45 +16,14 @@
 
 #include "healthd_mode_charger_nops.h"
 
-#include <health2/Health.h>
-#include <healthd/healthd.h>
+#include <health2impl/HalHealthLoop.h>
 
-#include <stdlib.h>
-#include <string.h>
+#include "charger_utils.h"
 
-using namespace android;
-
-// main healthd loop
-extern int healthd_main(void);
-
-// NOPs for modes that need no special action
-
-static void healthd_mode_nop_init(struct healthd_config* config);
-static int healthd_mode_nop_preparetowait(void);
-static void healthd_mode_nop_heartbeat(void);
-static void healthd_mode_nop_battery_update(struct android::BatteryProperties* props);
-
-static struct healthd_mode_ops healthd_nops = {
-        .init = healthd_mode_nop_init,
-        .preparetowait = healthd_mode_nop_preparetowait,
-        .heartbeat = healthd_mode_nop_heartbeat,
-        .battery_update = healthd_mode_nop_battery_update,
-};
-
-static void healthd_mode_nop_init(struct healthd_config* config) {
-    using android::hardware::health::V2_0::implementation::Health;
-    Health::initInstance(config);
-}
-
-static int healthd_mode_nop_preparetowait(void) {
-    return -1;
-}
-
-static void healthd_mode_nop_heartbeat(void) {}
-
-static void healthd_mode_nop_battery_update(struct android::BatteryProperties* /*props*/) {}
+using android::hardware::health::GetPassthroughHealth;
+using android::hardware::health::V2_1::implementation::HalHealthLoop;
 
 int healthd_charger_nops(int /* argc */, char** /* argv */) {
-    healthd_mode_ops = &healthd_nops;
-    return healthd_main();
+    HalHealthLoop charger("charger", GetPassthroughHealth());
+    return charger.StartLoop();
 }
diff --git a/healthd/include/healthd/BatteryMonitor.h b/healthd/include/healthd/BatteryMonitor.h
index 4d1d53f..d41a374 100644
--- a/healthd/include/healthd/BatteryMonitor.h
+++ b/healthd/include/healthd/BatteryMonitor.h
@@ -17,6 +17,8 @@
 #ifndef HEALTHD_BATTERYMONITOR_H
 #define HEALTHD_BATTERYMONITOR_H
 
+#include <memory>
+
 #include <batteryservice/BatteryService.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
@@ -24,6 +26,19 @@
 #include <healthd/healthd.h>
 
 namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+struct HealthInfo;
+}  // namespace V1_0
+namespace V2_0 {
+struct HealthInfo;
+}  // namespace V2_0
+namespace V2_1 {
+struct HealthInfo;
+}  // namespace V2_1
+}  // namespace health
+}  // namespace hardware
 
 class BatteryMonitor {
   public:
@@ -37,12 +52,19 @@
     };
 
     BatteryMonitor();
+    ~BatteryMonitor();
     void init(struct healthd_config *hc);
-    bool update(void);
     int getChargeStatus();
     status_t getProperty(int id, struct BatteryProperty *val);
     void dumpState(int fd);
-    friend struct BatteryProperties getBatteryProperties(BatteryMonitor* batteryMonitor);
+
+    const android::hardware::health::V1_0::HealthInfo& getHealthInfo_1_0() const;
+    const android::hardware::health::V2_0::HealthInfo& getHealthInfo_2_0() const;
+    const android::hardware::health::V2_1::HealthInfo& getHealthInfo_2_1() const;
+
+    void updateValues(void);
+    void logValues(void);
+    bool isChargerOnline();
 
   private:
     struct healthd_config *mHealthdConfig;
@@ -50,10 +72,8 @@
     bool mBatteryDevicePresent;
     int mBatteryFixedCapacity;
     int mBatteryFixedTemperature;
-    struct BatteryProperties props;
+    std::unique_ptr<android::hardware::health::V2_1::HealthInfo> mHealthInfo;
 
-    int getBatteryStatus(const char* status);
-    int getBatteryHealth(const char* status);
     int readFromFile(const String8& path, std::string* buf);
     PowerSupplyType readPowerSupplyType(const String8& path);
     bool getBooleanField(const String8& path);
diff --git a/init/Android.bp b/init/Android.bp
index 6be7290..42d0b33 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -26,6 +26,7 @@
         "-Wextra",
         "-Wno-unused-parameter",
         "-Werror",
+        "-DALLOW_FIRST_STAGE_CONSOLE=0",
         "-DALLOW_LOCAL_PROP_OVERRIDE=0",
         "-DALLOW_PERMISSIVE_SELINUX=0",
         "-DREBOOT_BOOTLOADER_ON_PANIC=0",
@@ -36,6 +37,8 @@
     product_variables: {
         debuggable: {
             cppflags: [
+                "-UALLOW_FIRST_STAGE_CONSOLE",
+                "-DALLOW_FIRST_STAGE_CONSOLE=1",
                 "-UALLOW_LOCAL_PROP_OVERRIDE",
                 "-DALLOW_LOCAL_PROP_OVERRIDE=1",
                 "-UALLOW_PERMISSIVE_SELINUX",
@@ -59,25 +62,25 @@
         },
     },
     static_libs: [
-        "libseccomp_policy",
         "libavb",
         "libc++fs",
         "libcgrouprc_format",
+        "liblmkd_utils",
+        "libmodprobe",
         "libprotobuf-cpp-lite",
         "libpropertyinfoserializer",
         "libpropertyinfoparser",
+        "libsnapshot_init",
+        "lib_apex_manifest_proto_lite",
     ],
     shared_libs: [
         "libbacktrace",
         "libbase",
-        "libbinder",
         "libbootloader_message",
         "libcutils",
-        "libcrypto",
         "libdl",
         "libext4_utils",
         "libfs_mgr",
-        "libfscrypt",
         "libgsi",
         "libhidl-gen-utils",
         "libkeyutils",
@@ -90,29 +93,34 @@
         "libutils",
     ],
     bootstrap: true,
+    visibility: [":__subpackages__"],
 }
 
 cc_library_static {
     name: "libinit",
     recovery_available: true,
-    defaults: ["init_defaults", "selinux_policy_version"],
+    defaults: [
+        "init_defaults",
+        "selinux_policy_version",
+    ],
     srcs: [
         "action.cpp",
         "action_manager.cpp",
         "action_parser.cpp",
-        "boringssl_self_test.cpp",
         "bootchart.cpp",
         "builtins.cpp",
         "capabilities.cpp",
-        "descriptors.cpp",
         "devices.cpp",
         "epoll.cpp",
         "firmware_handler.cpp",
         "first_stage_init.cpp",
         "first_stage_mount.cpp",
+        "fscrypt_init_extensions.cpp",
         "import_parser.cpp",
         "init.cpp",
+        "interface_utils.cpp",
         "keychords.cpp",
+        "lmkd_service.cpp",
         "modalias_handler.cpp",
         "mount_handler.cpp",
         "mount_namespace.cpp",
@@ -120,12 +128,17 @@
         "persistent_properties.cpp",
         "persistent_properties.proto",
         "property_service.cpp",
+        "property_service.proto",
         "property_type.cpp",
         "reboot.cpp",
         "reboot_utils.cpp",
         "security.cpp",
+        "selabel.cpp",
         "selinux.cpp",
         "service.cpp",
+        "service_list.cpp",
+        "service_parser.cpp",
+        "service_utils.cpp",
         "sigchld_handler.cpp",
         "subcontext.cpp",
         "subcontext.proto",
@@ -137,7 +150,11 @@
         "ueventd_parser.cpp",
         "util.cpp",
     ],
-    whole_static_libs: ["libcap", "com.android.sysprop.apex"],
+    whole_static_libs: [
+        "libcap",
+        "com.android.sysprop.apex",
+        "com.android.sysprop.init",
+    ],
     header_libs: ["bootimg_headers"],
     proto: {
         type: "lite",
@@ -147,11 +164,21 @@
     target: {
         recovery: {
             cflags: ["-DRECOVERY"],
-            exclude_shared_libs: ["libbinder", "libutils"],
+            exclude_shared_libs: [
+                "libbinder",
+                "libutils",
+            ],
         },
     },
 }
 
+phony {
+    name: "init",
+    required: [
+        "init_second_stage",
+    ],
+}
+
 cc_binary {
     name: "init_second_stage",
     recovery_available: true,
@@ -160,36 +187,51 @@
     static_libs: ["libinit"],
     required: [
         "e2fsdroid",
+        "init.rc",
         "mke2fs",
         "sload_f2fs",
         "make_f2fs",
+        "ueventd.rc",
     ],
     srcs: ["main.cpp"],
     symlinks: ["ueventd"],
     target: {
         recovery: {
             cflags: ["-DRECOVERY"],
-            exclude_shared_libs: ["libbinder", "libutils"],
+            exclude_shared_libs: [
+                "libbinder",
+                "libutils",
+            ],
         },
     },
-    ldflags: ["-Wl,--rpath,/system/${LIB}/bootstrap"],
 }
 
 // Tests
 // ------------------------------------------------------------------------------
 
 cc_test {
-    name: "init_tests",
+    name: "CtsInitTestCases",
     defaults: ["init_defaults"],
-    compile_multilib: "first",
+    require_root: true,
+
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
     srcs: [
         "devices_test.cpp",
+        "firmware_handler_test.cpp",
         "init_test.cpp",
         "keychords_test.cpp",
         "persistent_properties_test.cpp",
         "property_service_test.cpp",
         "property_type_test.cpp",
-        "result_test.cpp",
         "rlimit_parser_test.cpp",
         "service_test.cpp",
         "subcontext_test.cpp",
@@ -199,7 +241,12 @@
         "util_test.cpp",
     ],
     static_libs: ["libinit"],
-    test_suites: ["device-tests"],
+
+    test_suites: [
+        "cts",
+        "device-tests",
+        "vts",
+    ],
 }
 
 cc_benchmark {
@@ -216,9 +263,13 @@
 
 genrule {
     name: "generated_stub_builtin_function_map",
+    tool_files: ["host_builtin_map.py"],
     out: ["generated_stub_builtin_function_map.h"],
-    srcs: ["builtins.cpp"],
-    cmd: "sed -n '/Builtin-function-map start/{:a;n;/Builtin-function-map end/q;p;ba}' $(in) | sed -e 's/do_[^}]*/do_stub/g' > $(out)",
+    srcs: [
+        "builtins.cpp",
+        "check_builtins.cpp",
+    ],
+    cmd: "$(location host_builtin_map.py) --builtins $(location builtins.cpp) --check_builtins $(location check_builtins.cpp) > $(out)",
 }
 
 cc_binary {
@@ -234,31 +285,38 @@
     static_libs: [
         "libbase",
         "libselinux",
+        "libpropertyinfoserializer",
+        "libpropertyinfoparser",
     ],
     whole_static_libs: ["libcap"],
     shared_libs: [
-        "libprotobuf-cpp-lite",
-        "libhidl-gen-utils",
-        "libprocessgroup",
-        "liblog",
         "libcutils",
+        "libhidl-gen-utils",
+        "libhidlmetadata",
+        "liblog",
+        "libprocessgroup",
+        "libprotobuf-cpp-lite",
     ],
     srcs: [
         "action.cpp",
         "action_manager.cpp",
         "action_parser.cpp",
         "capabilities.cpp",
-        "descriptors.cpp",
+        "check_builtins.cpp",
         "epoll.cpp",
         "keychords.cpp",
         "import_parser.cpp",
+        "interface_utils.cpp",
         "host_import_parser.cpp",
         "host_init_verifier.cpp",
-        "host_init_stubs.cpp",
         "parser.cpp",
+        "property_type.cpp",
         "rlimit_parser.cpp",
         "tokenizer.cpp",
         "service.cpp",
+        "service_list.cpp",
+        "service_parser.cpp",
+        "service_utils.cpp",
         "subcontext.cpp",
         "subcontext.proto",
         "util.cpp",
@@ -268,7 +326,7 @@
     },
     generated_headers: [
         "generated_stub_builtin_function_map",
-        "generated_android_ids"
+        "generated_android_ids",
     ],
     target: {
         android: {
@@ -279,5 +337,3 @@
         },
     },
 }
-
-subdirs = ["*"]
diff --git a/init/Android.mk b/init/Android.mk
index c4f7d34..07b0f95 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -8,6 +8,7 @@
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
 init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=1 \
     -DALLOW_LOCAL_PROP_OVERRIDE=1 \
     -DALLOW_PERMISSIVE_SELINUX=1 \
     -DREBOOT_BOOTLOADER_ON_PANIC=1 \
@@ -15,6 +16,7 @@
     -DDUMP_ON_UMOUNT_FAILURE=1
 else
 init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=0 \
     -DALLOW_LOCAL_PROP_OVERRIDE=0 \
     -DALLOW_PERMISSIVE_SELINUX=0 \
     -DREBOOT_BOOTLOADER_ON_PANIC=0 \
@@ -50,8 +52,8 @@
     first_stage_init.cpp \
     first_stage_main.cpp \
     first_stage_mount.cpp \
-    mount_namespace.cpp \
     reboot_utils.cpp \
+    selabel.cpp \
     selinux.cpp \
     switch_root.cpp \
     uevent_listener.cpp \
@@ -70,9 +72,8 @@
 LOCAL_REQUIRED_MODULES := \
    adb_debug.prop \
 
-# Set up the same mount points on the ramdisk that system-as-root contains.
+# Set up the directories that first stage init mounts on.
 LOCAL_POST_INSTALL_CMD := mkdir -p \
-    $(TARGET_RAMDISK_OUT)/apex \
     $(TARGET_RAMDISK_OUT)/debug_ramdisk \
     $(TARGET_RAMDISK_OUT)/dev \
     $(TARGET_RAMDISK_OUT)/mnt \
@@ -88,8 +89,6 @@
     libsquashfs_utils \
     liblogwrap \
     libext4_utils \
-    libfscrypt \
-    libseccomp_policy \
     libcrypto_utils \
     libsparse \
     libavb \
@@ -98,7 +97,7 @@
     libcutils \
     libbase \
     liblog \
-    libcrypto \
+    libcrypto_static \
     libdl \
     libz \
     libselinux \
@@ -106,9 +105,13 @@
     libgsi \
     libcom.android.sysprop.apex \
     liblzma \
-    libdexfile_support \
+    libdexfile_support_static \
     libunwindstack \
     libbacktrace \
+    libmodprobe \
+    libext2_uuid \
+    libprotobuf-cpp-lite \
+    libsnapshot_init \
 
 LOCAL_SANITIZE := signed-integer-overflow
 # First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/init/AndroidTest.xml b/init/AndroidTest.xml
new file mode 100644
index 0000000..667911d
--- /dev/null
+++ b/init/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for CTS init 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="not_multi_abi" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="CtsInitTestCases->/data/local/tmp/CtsInitTestCases" />
+        <option name="append-bitness" value="true" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="CtsInitTestCases" />
+        <option name="runtime-hint" value="65s" />
+    </test>
+</configuration>
diff --git a/init/README.md b/init/README.md
index 1b8b848..b8300fa 100644
--- a/init/README.md
+++ b/init/README.md
@@ -35,29 +35,19 @@
 at the beginning of its execution.  It is responsible for the initial
 set up of the system.
 
-Devices that mount /system, /vendor through the first stage mount mechanism
-load all of the files contained within the
+Init loads all of the files contained within the
 /{system,vendor,odm}/etc/init/ directories immediately after loading
 the primary /init.rc.  This is explained in more details in the
 Imports section of this file.
 
-Legacy devices without the first stage mount mechanism do the following:
-1. /init.rc imports /init.${ro.hardware}.rc which is the primary
-   vendor supplied .rc file.
-2. During the mount\_all command, the init executable loads all of the
-   files contained within the /{system,vendor,odm}/etc/init/ directories.
-   These directories are intended for all Actions and Services used after
-   file system mounting.
-
-One may specify paths in the mount\_all command line to have it import
-.rc files at the specified paths instead of the default ones listed above.
-This is primarily for supporting factory mode and other non-standard boot
-modes.  The three default paths should be used for the normal boot process.
+Legacy devices without the first stage mount mechanism previously were
+able to import init scripts during mount_all, however that is deprecated
+and not allowed for devices launching after Q.
 
 The intention of these directories is:
 
    1. /system/etc/init/ is for core system items such as
-      SurfaceFlinger, MediaService, and logcatd.
+      SurfaceFlinger, MediaService, and logd.
    2. /vendor/etc/init/ is for SoC vendor items such as actions or
       daemons needed for core SoC functionality.
    3. /odm/etc/init/ is for device manufacturer items such as
@@ -72,7 +62,7 @@
 init .rc file should additionally contain any actions associated with
 its service.
 
-An example is the logcatd.rc and Android.mk files located in the
+An example is the userdebug logcatd.rc and Android.mk files located in the
 system/core/logcat directory.  The LOCAL\_INIT\_RC macro in the
 Android.mk file places logcatd.rc in /system/etc/init/ during the
 build process.  Init loads logcatd.rc during the mount\_all command and
@@ -88,14 +78,6 @@
 conflict resolution when multiple services are added to the system, as
 each one will go into a separate file.
 
-There are two options "early" and "late" in mount\_all command
-which can be set after optional paths. With "--early" set, the
-init executable will skip mounting entries with "latemount" flag
-and triggering fs encryption state event. With "--late" set,
-init executable will only mount entries with "latemount" flag but skip
-importing rc files. By default, no option is set, and mount\_all will
-process all entries in the given fstab.
-
 Actions
 -------
 Actions are named sequences of commands.  Actions have a trigger which
@@ -188,6 +170,8 @@
   be changed by setting the "androidboot.console" kernel parameter. In
   all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be
   specified as just "console tty0".
+  This option connects stdin, stdout, and stderr to the console. It is mutually exclusive with the
+  stdio_to_kmsg option, which only connects stdout and stderr to kmsg.
 
 `critical`
 > This is a device-critical service. If it exits more than four times in
@@ -214,9 +198,9 @@
 
 `interface <interface name> <instance name>`
 > Associates this service with a list of the HIDL services that it provides. The interface name
-  must be a fully-qualified name and not a value name. This is used to allow hwservicemanager to
-  lazily start services. When multiple interfaces are served, this tag should be used multiple
-  times.
+  must be a fully-qualified name and not a value name. For instance, this is used to allow
+  hwservicemanager to lazily start services. When multiple interfaces are served, this tag should
+  be used multiple times.
   For example: interface vendor.foo.bar@1.0::IBaz default
 
 `ioprio <class> <priority>`
@@ -281,6 +265,12 @@
 > Scheduling priority of the service process. This value has to be in range
   -20 to 19. Default priority is 0. Priority is set via setpriority().
 
+`reboot_on_failure <target>`
+> If this process cannot be started or if the process terminates with an exit code other than
+  CLD_EXITED or an status other than '0', reboot the system with the target specified in
+  _target_. _target_ takes the same format as the parameter to sys.powerctl. This is particularly
+  intended to be used with the `exec_start` builtin for any must-have checks during boot.
+
 `restart_period <seconds>`
 > If a non-oneshot service exits, it will be restarted at its start time plus
   this period. It defaults to 5s to rate limit crashing services.
@@ -317,13 +307,21 @@
   See the below section on debugging for how this can be used.
 
 `socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]`
-> Create a unix domain socket named /dev/socket/_name_ and pass its fd to the
-  launched process.  _type_ must be "dgram", "stream" or "seqpacket".  User and
+> Create a UNIX domain socket named /dev/socket/_name_ and pass its fd to the
+  launched process.  _type_ must be "dgram", "stream" or "seqpacket".  _type_
+  may end with "+passcred" to enable SO_PASSCRED on the socket. User and
   group default to 0.  'seclabel' is the SELinux security context for the
   socket.  It defaults to the service security context, as specified by
   seclabel or computed based on the service executable file security context.
   For native executables see libcutils android\_get\_control\_socket().
 
+`stdio_to_kmsg`
+> Redirect stdout and stderr to /dev/kmsg_debug. This is useful for services that do not use native
+  Android logging during early boot and whose logs messages we want to capture. This is only enabled
+  when /dev/kmsg_debug is enabled, which is only enabled on userdebug and eng builds.
+  This is mutually exclusive with the console option, which additionally connects stdin to the
+  given console.
+
 `timeout_period <seconds>`
 > Provide a timeout after which point the service will be killed. The oneshot keyword is respected
   here, so oneshot services do not automatically restart, however all other services will.
@@ -497,32 +495,49 @@
   This is included in the default init.rc.
 
 `loglevel <level>`
-> Sets the kernel log level to level. Properties are expanded within _level_.
+> Sets init's log level to the integer level, from 7 (all logging) to 0
+  (fatal logging only). The numeric values correspond to the kernel log
+  levels, but this command does not affect the kernel log level. Use the
+  `write` command to write to `/proc/sys/kernel/printk` to change that.
+  Properties are expanded within _level_.
 
 `mark_post_data`
 > Used to mark the point right after /data is mounted. Used to implement the
   `class_reset_post_data` and `class_start_post_data` commands.
 
-`mkdir <path> [mode] [owner] [group]`
+`mkdir <path> [<mode>] [<owner>] [<group>] [encryption=<action>] [key=<key>]`
 > Create a directory at _path_, optionally with the given mode, owner, and
   group. If not provided, the directory is created with permissions 755 and
   owned by the root user and root group. If provided, the mode, owner and group
   will be updated if the directory exists already.
 
+ > _action_ can be one of:
+  * `None`: take no encryption action; directory will be encrypted if parent is.
+  * `Require`: encrypt directory, abort boot process if encryption fails
+  * `Attempt`: try to set an encryption policy, but continue if it fails
+  * `DeleteIfNecessary`: recursively delete directory if necessary to set
+  encryption policy.
+
+  > _key_ can be one of:
+  * `ref`: use the systemwide DE key
+  * `per_boot_ref`: use the key freshly generated on each boot.
+
 `mount_all <fstab> [ <path> ]\* [--<option>]`
-> Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab and imports .rc files
-  at the specified paths (e.g., on the partitions just mounted) with optional
+> Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional
   options "early" and "late".
-  Refer to the section of "Init .rc Files" for detail.
+  With "--early" set, the init executable will skip mounting entries with
+  "latemount" flag and triggering fs encryption state event. With "--late" set,
+  init executable will only mount entries with "latemount" flag. By default,
+  no option is set, and mount\_all will process all entries in the given fstab.
 
 `mount <type> <device> <dir> [ <flag>\* ] [<options>]`
 > Attempt to mount the named device at the directory _dir_
   _flag_s include "ro", "rw", "remount", "noatime", ...
   _options_ include "barrier=1", "noauto\_da\_alloc", "discard", ... as
-  a comma separated string, eg: barrier=1,noauto\_da\_alloc
+  a comma separated string, e.g. barrier=1,noauto\_da\_alloc
 
 `parse_apex_configs`
-> Parses config file(s) from the mounted APEXes. Intented to be used only once
+> Parses config file(s) from the mounted APEXes. Intended to be used only once
   when apexd notifies the mount event by setting apexd.status to ready.
 
 `restart <service>`
@@ -568,6 +583,7 @@
   Note that this is _not_ synchronous, and even if it were, there is
   no guarantee that the operating system's scheduler will execute the
   service sufficiently to guarantee anything about the service's status.
+  See the `exec_start` command for a synchronous version of `start`.
 
 > This creates an important consequence that if the service offers
   functionality to other services, such as providing a
@@ -585,7 +601,7 @@
 `symlink <target> <path>`
 > Create a symbolic link at _path_ with the value _target_
 
-`sysclktz <mins_west_of_gmt>`
+`sysclktz <minutes_west_of_gmt>`
 > Set the system clock base (0 if system clock ticks in GMT)
 
 `trigger <event>`
@@ -595,9 +611,6 @@
 `umount <path>`
 > Unmount the filesystem mounted at that path.
 
-`verity_load_state`
-> Internal implementation detail used to load dm-verity state.
-
 `verity_update_state <mount-point>`
 > Internal implementation detail used to update dm-verity state and
   set the partition._mount-point_.verified properties used by adb remount
@@ -637,8 +650,9 @@
       `ro.boot.init_rc` during initial boot.
    2. When it imports /{system,vendor,odm}/etc/init/ for first stage mount
       devices immediately after importing /init.rc.
-   3. When it imports /{system,vendor,odm}/etc/init/ or .rc files at specified
-      paths during mount_all.
+   3. (Deprecated) When it imports /{system,vendor,odm}/etc/init/ or .rc files
+      at specified paths during mount_all, not allowed for devices launching
+      after Q.
 
 The order that files are imported is a bit complex for legacy reasons
 and to keep backwards compatibility.  It is not strictly guaranteed.
@@ -648,7 +662,7 @@
 earlier executed trigger, or 2) place it in an Action with the same
 trigger within the same file at an earlier line.
 
-Nonetheless, the defacto order for first stage mount devices is:
+Nonetheless, the de facto order for first stage mount devices is:
 1. /init.rc is parsed then recursively each of its imports are
    parsed.
 2. The contents of /system/etc/init/ are alphabetized and parsed
@@ -695,8 +709,11 @@
 > Time after boot in ns (via the CLOCK\_BOOTTIME clock) at which the first
   stage of init started.
 
+`ro.boottime.init.first_stage`
+> How long in ns it took to run first stage.
+
 `ro.boottime.init.selinux`
-> How long it took the first stage to initialize SELinux.
+> How long in ns it took to run SELinux stage.
 
 `ro.boottime.init.cold_boot_wait`
 > How long init waited for ueventd's coldboot phase to end.
@@ -738,7 +755,7 @@
 A handy script named compare-bootcharts.py can be used to compare the
 start/end time of selected processes. The aforementioned grab-bootchart.sh
 will leave a bootchart tarball named bootchart.tgz at /tmp/android-bootchart.
-If two such barballs are preserved on the host machine under different
+If two such tarballs are preserved on the host machine under different
 directories, the script can list the timestamps differences. For example:
 
 Usage: system/core/init/compare-bootcharts.py _base-bootchart-dir_ _exp-bootchart-dir_
@@ -779,6 +796,12 @@
 
 Debugging init
 --------------
+When a service starts from init, it may fail to `execv()` the service. This is not typical, and may
+point to an error happening in the linker as the new service is started. The linker in Android
+prints its logs to `logd` and `stderr`, so they are visible in `logcat`. If the error is encountered
+before it is possible to access `logcat`, the `stdio_to_kmsg` service option may be used to direct
+the logs that the linker prints to `stderr` to `kmsg`, where they can be read via a serial port.
+
 Launching init services without init is not recommended as init sets up a significant amount of
 environment (user, groups, security label, capabilities, etc) that is hard to replicate manually.
 
@@ -786,7 +809,7 @@
 This option will send SIGSTOP to a service immediately before calling exec. This gives a window
 where developers can attach a debugger, strace, etc before continuing the service with SIGCONT.
 
-This flag can also be dynamically controled via the ctl.sigstop_on and ctl.sigstop_off properties.
+This flag can also be dynamically controlled via the ctl.sigstop_on and ctl.sigstop_off properties.
 
 Below is an example of dynamically debugging logd via the above:
 
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
new file mode 100644
index 0000000..053ebf8
--- /dev/null
+++ b/init/README.ueventd.md
@@ -0,0 +1,138 @@
+# Ueventd
+-------
+Ueventd manages `/dev`, sets permissions for `/sys`, and handles firmware uevents. It has default
+behavior described below, along with a scripting language that allows customizing this behavior,
+built on the same parser as init.
+
+Ueventd has one generic customization parameter, the size of rcvbuf_size for the ueventd socket. It
+is customized by the `uevent_socket_rcvbuf_size` parameter, which takes the format of
+
+    uevent_socket_rcvbuf_size <size>
+For example
+
+    uevent_socket_rcvbuf_size 16M
+Sets the uevent socket rcvbuf_size to 16 megabytes.
+
+## /dev
+----
+Ueventd listens to the kernel uevent sockets and creates/deletes nodes in `/dev` based on the
+incoming add/remove uevents. It defaults to using `0600` mode and `root` user/group. It always
+creates the nodes with the SELabel from the current loaded SEPolicy. It has three default behaviors
+for the node path:
+
+  1. Block devices are created as `/dev/block/<basename uevent DEVPATH>`. There are symlinks created
+     to this node at `/dev/block/<type>/<parent device>/<basename uevent DEVPATH>`,
+     `/dev/block/<type>/<parent device>/by-name/<uevent PARTNAME>`, and `/dev/block/by-name/<uevent
+     PARTNAME>` if the device is a boot device.
+  2. USB devices are created as `/dev/<uevent DEVNAME>` if `DEVNAME` was specified for the uevent,
+     otherwise as `/dev/bus/usb/<bus_id>/<device_id>` where `bus_id` is `uevent MINOR / 128 + 1` and
+     `device_id` is `uevent MINOR % 128 + 1`.
+  3. All other devices are created as `/dev/<basename uevent DEVPATH>`
+
+The permissions can be modified using a ueventd.rc script and a line that beings with `/dev`. These
+lines take the format of
+
+    devname mode uid gid
+For example
+
+    /dev/null 0666 root root
+When `/dev/null` is created, its mode will be set to `0666`, its user to `root` and its group to
+`root`.
+
+The path can be modified using a ueventd.rc script and a `subsystem` section. There are three to set
+for a subsystem: the subsystem name, which device name to use, and which directory to place the
+device in. The section takes the below format of
+
+    subsystem <subsystem_name>
+      devname uevent_devname|uevent_devpath
+      [dirname <directory>]
+
+`subsystem_name` is used to match uevent `SUBSYSTEM` value
+
+`devname` takes one of two options
+  1. `uevent_devname` specifies that the name of the node will be the uevent `DEVNAME`
+  2. `uevent_devpath` specified that the name of the node will be basename uevent `DEVPATH`
+
+`dirname` is an optional parameter that specifies a directory within `/dev` where the node will be
+created.
+
+For example
+
+    subsystem sound
+      devname uevent_devpath
+      dirname /dev/snd
+Indicates that all uevents with `SUBSYSTEM=sound` will create nodes as `/dev/snd/<basename uevent
+DEVPATH>`.
+
+## /sys
+----
+Ueventd by default takes no action for `/sys`, however it can be instructed to set permissions for
+certain files in `/sys` when matching uevents are generated. This is done using a ueventd.rc script
+and a line that begins with `/sys`. These lines take the format of
+
+    nodename attr mode uid gid
+For example
+
+    /sys/devices/system/cpu/cpu* cpufreq/scaling_max_freq 0664 system system
+When a uevent that matches the pattern `/sys/devices/system/cpu/cpu*` is sent, the matching sysfs
+attribute, `cpufreq/scaling_max_freq`, will have its mode set to `0664`, its user to to `system` and
+its group set to `system`.
+
+Note that `*` matches as a wildcard and can be used anywhere in a path.
+
+## Firmware loading
+----------------
+Ueventd by default serves firmware requests by searching through a list of firmware directories
+for a file matching the uevent `FIRMWARE`. It then forks a process to serve this firmware to the
+kernel.
+
+The list of firmware directories is customized by a `firmware_directories` line in a ueventd.rc
+file. This line takes the format of
+
+    firmware_directories <firmware_directory> [ <firmware_directory> ]*
+For example
+
+    firmware_directories /etc/firmware/ /odm/firmware/ /vendor/firmware/ /firmware/image/
+Adds those 4 directories, in that order to the list of firmware directories that will be tried by
+ueventd. Note that this option always accumulates to the list; it is not possible to remove previous
+entries.
+
+Ueventd will wait until after `post-fs` in init, to keep retrying before believing the firmwares are
+not present.
+
+The exact firmware file to be served can be customized by running an external program by a
+`external_firmware_handler` line in a ueventd.rc file. This line takes the format of
+
+    external_firmware_handler <devpath> <user name to run as> <path to external program>
+For example
+
+    external_firmware_handler /devices/leds/red/firmware/coeffs.bin system /vendor/bin/led_coeffs.bin
+Will launch `/vendor/bin/led_coeffs.bin` as the system user instead of serving the default firmware
+for `/devices/leds/red/firmware/coeffs.bin`.
+
+Ueventd will provide the uevent `DEVPATH` and `FIRMWARE` to this external program on the environment
+via environment variables with the same names. Ueventd will use the string written to stdout as the
+new name of the firmware to load. It will still look for the new firmware in the list of firmware
+directories stated above. It will also reject file names with `..` in them, to prevent leaving these
+directories. If stdout cannot be read, or the program returns with any exit code other than
+`EXIT_SUCCESS`, or the program crashes, the default firmware from the uevent will be loaded.
+
+Ueventd will additionally log all messages sent to stderr from the external program to the serial
+console after the external program has exited.
+
+## Coldboot
+--------
+Ueventd must create devices in `/dev` for all devices that have already sent their uevents before
+ueventd has started. To do so, when ueventd is started it does what it calls a 'coldboot' on `/sys`,
+in which it writes 'add' to every 'uevent' file that it finds in `/sys/class`, `/sys/block`, and
+`/sys/devices`. This causes the kernel to regenerate the uevents for these paths, and thus for
+ueventd to create the nodes.
+
+For boot time purposes, this is done in parallel across a set of child processes. `ueventd.cpp` in
+this directory contains documentation on how the parallelization is done.
+
+There is an option to parallelize the restorecon function during cold boot as well. This should only
+be done for devices that do not use genfscon, which is the recommended method for labeling sysfs
+nodes. To enable this option, use the below line in a ueventd.rc script:
+
+    parallel_restorecon enabled
diff --git a/init/action.cpp b/init/action.cpp
index 94ccef2..f05fa7c 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -28,17 +28,18 @@
 namespace android {
 namespace init {
 
-Result<Success> RunBuiltinFunction(const BuiltinFunction& function,
-                                   const std::vector<std::string>& args,
-                                   const std::string& context) {
+Result<void> RunBuiltinFunction(const BuiltinFunction& function,
+                                const std::vector<std::string>& args, const std::string& context) {
     auto builtin_arguments = BuiltinArguments(context);
 
     builtin_arguments.args.resize(args.size());
     builtin_arguments.args[0] = args[0];
     for (std::size_t i = 1; i < args.size(); ++i) {
-        if (!expand_props(args[i], &builtin_arguments.args[i])) {
-            return Error() << "cannot expand '" << args[i] << "'";
+        auto expanded_arg = ExpandProps(args[i]);
+        if (!expanded_arg) {
+            return expanded_arg.error();
         }
+        builtin_arguments.args[i] = std::move(*expanded_arg);
     }
 
     return function(builtin_arguments);
@@ -51,7 +52,7 @@
       args_(std::move(args)),
       line_(line) {}
 
-Result<Success> Command::InvokeFunc(Subcontext* subcontext) const {
+Result<void> Command::InvokeFunc(Subcontext* subcontext) const {
     if (subcontext) {
         if (execute_in_subcontext_) {
             return subcontext->Execute(args_);
@@ -67,6 +68,30 @@
     return RunBuiltinFunction(func_, args_, kInitContext);
 }
 
+Result<void> Command::CheckCommand() const {
+    auto builtin_arguments = BuiltinArguments("host_init_verifier");
+
+    builtin_arguments.args.resize(args_.size());
+    builtin_arguments.args[0] = args_[0];
+    for (size_t i = 1; i < args_.size(); ++i) {
+        auto expanded_arg = ExpandProps(args_[i]);
+        if (!expanded_arg) {
+            if (expanded_arg.error().message().find("doesn't exist while expanding") !=
+                std::string::npos) {
+                // If we failed because we won't have a property, use an empty string, which is
+                // never returned from the parser, to indicate that this field cannot be checked.
+                builtin_arguments.args[i] = "";
+            } else {
+                return expanded_arg.error();
+            }
+        } else {
+            builtin_arguments.args[i] = std::move(*expanded_arg);
+        }
+    }
+
+    return func_(builtin_arguments);
+}
+
 std::string Command::BuildCommandString() const {
     return Join(args_, ' ');
 }
@@ -81,28 +106,43 @@
       filename_(filename),
       line_(line) {}
 
-const KeywordFunctionMap* Action::function_map_ = nullptr;
+const BuiltinFunctionMap* Action::function_map_ = nullptr;
 
-Result<Success> Action::AddCommand(std::vector<std::string>&& args, int line) {
+Result<void> Action::AddCommand(std::vector<std::string>&& args, int line) {
     if (!function_map_) {
         return Error() << "no function map available";
     }
 
-    auto function = function_map_->FindFunction(args);
-    if (!function) return Error() << function.error();
+    auto map_result = function_map_->Find(args);
+    if (!map_result) {
+        return Error() << map_result.error();
+    }
 
-    commands_.emplace_back(function->second, function->first, std::move(args), line);
-    return Success();
+    commands_.emplace_back(map_result->function, map_result->run_in_subcontext, std::move(args),
+                           line);
+    return {};
 }
 
 void Action::AddCommand(BuiltinFunction f, std::vector<std::string>&& args, int line) {
-    commands_.emplace_back(f, false, std::move(args), line);
+    commands_.emplace_back(std::move(f), false, std::move(args), line);
 }
 
 std::size_t Action::NumCommands() const {
     return commands_.size();
 }
 
+size_t Action::CheckAllCommands() const {
+    size_t failures = 0;
+    for (const auto& command : commands_) {
+        if (auto result = command.CheckCommand(); !result) {
+            LOG(ERROR) << "Command '" << command.BuildCommandString() << "' (" << filename_ << ":"
+                       << command.line() << ") failed: " << result.error();
+            ++failures;
+        }
+    }
+    return failures;
+}
+
 void Action::ExecuteOneCommand(std::size_t command) const {
     // We need a copy here since some Command execution may result in
     // changing commands_ vector by importing .rc files through parser
@@ -121,25 +161,15 @@
     auto result = command.InvokeFunc(subcontext_);
     auto duration = t.duration();
 
-    // There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
-    // device, such as '/sys/class/leds/jogball-backlight/brightness'.  As of this writing, there
-    // are 198 such failures on bullhead.  Instead of spamming the log reporting them, we do not
-    // report such failures unless we're running at the DEBUG log level.
-    bool report_failure = !result.has_value();
-    if (report_failure && android::base::GetMinimumLogSeverity() > android::base::DEBUG &&
-        result.error_errno() == ENOENT) {
-        report_failure = false;
-    }
-
     // Any action longer than 50ms will be warned to user as slow operation
-    if (report_failure || duration > 50ms ||
+    if (!result.has_value() || duration > 50ms ||
         android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
         std::string trigger_name = BuildTriggersString();
         std::string cmd_str = command.BuildCommandString();
 
         LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_
                   << ":" << command.line() << ") took " << duration.count() << "ms and "
-                  << (result ? "succeeded" : "failed: " + result.error_string());
+                  << (result ? "succeeded" : "failed: " + result.error().message());
     }
 }
 
@@ -150,28 +180,32 @@
 // It takes an optional (name, value) pair, which if provided must
 // be present in property_triggers_; it skips the check of the current
 // property value for this pair.
-bool Action::CheckPropertyTriggers(const std::string& name,
-                                   const std::string& value) const {
+bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const {
     if (property_triggers_.empty()) {
         return true;
     }
 
-    bool found = name.empty();
-    for (const auto& [trigger_name, trigger_value] : property_triggers_) {
-        if (trigger_name == name) {
-            if (trigger_value != "*" && trigger_value != value) {
-                return false;
-            } else {
-                found = true;
-            }
-        } else {
-            std::string prop_val = android::base::GetProperty(trigger_name, "");
-            if (prop_val.empty() || (trigger_value != "*" && trigger_value != prop_val)) {
-                return false;
-            }
+    if (!name.empty()) {
+        auto it = property_triggers_.find(name);
+        if (it == property_triggers_.end()) {
+            return false;
+        }
+        const auto& trigger_value = it->second;
+        if (trigger_value != "*" && trigger_value != value) {
+            return false;
         }
     }
-    return found;
+
+    for (const auto& [trigger_name, trigger_value] : property_triggers_) {
+        if (trigger_name != name) {
+            std::string prop_value = android::base::GetProperty(trigger_name, "");
+            if (trigger_value == "*" && !prop_value.empty()) {
+                continue;
+            }
+            if (trigger_value != prop_value) return false;
+        }
+    }
+    return true;
 }
 
 bool Action::CheckEvent(const EventTrigger& event_trigger) const {
diff --git a/init/action.h b/init/action.h
index 967c682..1534bf9 100644
--- a/init/action.h
+++ b/init/action.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_ACTION_H
-#define _INIT_ACTION_H
+#pragma once
 
 #include <map>
 #include <queue>
@@ -31,16 +30,17 @@
 namespace android {
 namespace init {
 
-Result<Success> RunBuiltinFunction(const BuiltinFunction& function,
-                                   const std::vector<std::string>& args, const std::string& context);
+Result<void> RunBuiltinFunction(const BuiltinFunction& function,
+                                const std::vector<std::string>& args, const std::string& context);
 
 class Command {
   public:
     Command(BuiltinFunction f, bool execute_in_subcontext, std::vector<std::string>&& args,
             int line);
 
-    Result<Success> InvokeFunc(Subcontext* subcontext) const;
+    Result<void> InvokeFunc(Subcontext* subcontext) const;
     std::string BuildCommandString() const;
+    Result<void> CheckCommand() const;
 
     int line() const { return line_; }
 
@@ -61,9 +61,9 @@
            const std::string& event_trigger,
            const std::map<std::string, std::string>& property_triggers);
 
-    Result<Success> AddCommand(std::vector<std::string>&& args, int line);
+    Result<void> AddCommand(std::vector<std::string>&& args, int line);
     void AddCommand(BuiltinFunction f, std::vector<std::string>&& args, int line);
-    std::size_t NumCommands() const;
+    size_t NumCommands() const;
     void ExecuteOneCommand(std::size_t command) const;
     void ExecuteAllCommands() const;
     bool CheckEvent(const EventTrigger& event_trigger) const;
@@ -71,11 +71,12 @@
     bool CheckEvent(const BuiltinAction& builtin_action) const;
     std::string BuildTriggersString() const;
     void DumpState() const;
+    size_t CheckAllCommands() const;
 
     bool oneshot() const { return oneshot_; }
     const std::string& filename() const { return filename_; }
     int line() const { return line_; }
-    static void set_function_map(const KeywordFunctionMap* function_map) {
+    static void set_function_map(const BuiltinFunctionMap* function_map) {
         function_map_ = function_map;
     }
 
@@ -91,10 +92,8 @@
     Subcontext* subcontext_;
     std::string filename_;
     int line_;
-    static const KeywordFunctionMap* function_map_;
+    static const BuiltinFunctionMap* function_map_;
 };
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
index 9de4085..ebca762 100644
--- a/init/action_manager.cpp
+++ b/init/action_manager.cpp
@@ -23,6 +23,14 @@
 
 ActionManager::ActionManager() : current_command_(0) {}
 
+size_t ActionManager::CheckAllCommands() {
+    size_t failures = 0;
+    for (const auto& action : actions_) {
+        failures += action->CheckAllCommands();
+    }
+    return failures;
+}
+
 ActionManager& ActionManager::GetInstance() {
     static ActionManager instance;
     return instance;
@@ -47,7 +55,7 @@
 void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
     auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
                                            std::map<std::string, std::string>{});
-    action->AddCommand(func, {name}, 0);
+    action->AddCommand(std::move(func), {name}, 0);
 
     event_queue_.emplace(action.get());
     actions_.emplace_back(std::move(action));
@@ -88,7 +96,8 @@
         current_command_ = 0;
         if (action->oneshot()) {
             auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
-            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
+            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
+                           actions_.end());
         }
     }
 }
diff --git a/init/action_manager.h b/init/action_manager.h
index 5f47a6d..a2b95ac 100644
--- a/init/action_manager.h
+++ b/init/action_manager.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_ACTION_MANAGER_H
-#define _INIT_ACTION_MANAGER_H
+#pragma once
 
 #include <string>
 #include <vector>
@@ -32,6 +31,7 @@
 
     // Exposed for testing
     ActionManager();
+    size_t CheckAllCommands();
 
     void AddAction(std::unique_ptr<Action> action);
     void QueueEventTrigger(const std::string& trigger);
@@ -55,5 +55,3 @@
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
index 4f8bd16..a8e1e09 100644
--- a/init/action_parser.cpp
+++ b/init/action_parser.cpp
@@ -16,11 +16,14 @@
 
 #include "action_parser.h"
 
+#include <ctype.h>
+
 #include <android-base/properties.h>
 #include <android-base/strings.h>
 
 #if defined(__ANDROID__)
 #include "property_service.h"
+#include "selinux.h"
 #else
 #include "host_init_stubs.h"
 #endif
@@ -55,8 +58,8 @@
     return CanReadProperty(subcontext->context(), prop_name);
 }
 
-Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
-                                     std::map<std::string, std::string>* property_triggers) {
+Result<void> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
+                                  std::map<std::string, std::string>* property_triggers) {
     const static std::string prop_str("property:");
     std::string prop_name(trigger.substr(prop_str.length()));
     size_t equal_pos = prop_name.find('=');
@@ -74,12 +77,23 @@
     if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
         return Error() << "multiple property triggers found for same property";
     }
-    return Success();
+    return {};
 }
 
-Result<Success> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
-                              std::string* event_trigger,
-                              std::map<std::string, std::string>* property_triggers) {
+Result<void> ValidateEventTrigger(const std::string& event_trigger) {
+    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
+        for (const char& c : event_trigger) {
+            if (c != '_' && c != '-' && !std::isalnum(c)) {
+                return Error() << "Illegal character '" << c << "' in '" << event_trigger << "'";
+            }
+        }
+    }
+    return {};
+}
+
+Result<void> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
+                           std::string* event_trigger,
+                           std::map<std::string, std::string>* property_triggers) {
     const static std::string prop_str("property:");
     for (std::size_t i = 0; i < args.size(); ++i) {
         if (args[i].empty()) {
@@ -103,31 +117,29 @@
             if (!event_trigger->empty()) {
                 return Error() << "multiple event triggers are not allowed";
             }
+            if (auto result = ValidateEventTrigger(args[i]); !result) {
+                return result;
+            }
 
             *event_trigger = args[i];
         }
     }
 
-    return Success();
+    return {};
 }
 
 }  // namespace
 
-Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
-                                           const std::string& filename, int line) {
+Result<void> ActionParser::ParseSection(std::vector<std::string>&& args,
+                                        const std::string& filename, int line) {
     std::vector<std::string> triggers(args.begin() + 1, args.end());
     if (triggers.size() < 1) {
         return Error() << "Actions must have a trigger";
     }
 
     Subcontext* action_subcontext = nullptr;
-    if (subcontexts_) {
-        for (auto& subcontext : *subcontexts_) {
-            if (StartsWith(filename, subcontext.path_prefix())) {
-                action_subcontext = &subcontext;
-                break;
-            }
-        }
+    if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
+        action_subcontext = subcontext_;
     }
 
     std::string event_trigger;
@@ -142,19 +154,19 @@
                                            property_triggers);
 
     action_ = std::move(action);
-    return Success();
+    return {};
 }
 
-Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
-    return action_ ? action_->AddCommand(std::move(args), line) : Success();
+Result<void> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
+    return action_ ? action_->AddCommand(std::move(args), line) : Result<void>{};
 }
 
-Result<Success> ActionParser::EndSection() {
+Result<void> ActionParser::EndSection() {
     if (action_ && action_->NumCommands() > 0) {
         action_manager_->AddAction(std::move(action_));
     }
 
-    return Success();
+    return {};
 }
 
 }  // namespace init
diff --git a/init/action_parser.h b/init/action_parser.h
index b7f7074..3000132 100644
--- a/init/action_parser.h
+++ b/init/action_parser.h
@@ -30,16 +30,16 @@
 
 class ActionParser : public SectionParser {
   public:
-    ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
-        : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
-    Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
-                                 int line) override;
-    Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
-    Result<Success> EndSection() override;
+    ActionParser(ActionManager* action_manager, Subcontext* subcontext)
+        : action_manager_(action_manager), subcontext_(subcontext), action_(nullptr) {}
+    Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
+                              int line) override;
+    Result<void> ParseLineSection(std::vector<std::string>&& args, int line) override;
+    Result<void> EndSection() override;
 
   private:
     ActionManager* action_manager_;
-    std::vector<Subcontext>* subcontexts_;
+    Subcontext* subcontext_;
     std::unique_ptr<Action> action_;
 };
 
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index c2cf573..b7db9b6 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -165,20 +165,20 @@
   LOG(INFO) << "Bootcharting finished";
 }
 
-static Result<Success> do_bootchart_start() {
+static Result<void> do_bootchart_start() {
     // We don't care about the content, but we do care that /data/bootchart/enabled actually exists.
     std::string start;
     if (!android::base::ReadFileToString("/data/bootchart/enabled", &start)) {
         LOG(VERBOSE) << "Not bootcharting";
-        return Success();
+        return {};
     }
 
     g_bootcharting_thread = new std::thread(bootchart_thread_main);
-    return Success();
+    return {};
 }
 
-static Result<Success> do_bootchart_stop() {
-    if (!g_bootcharting_thread) return Success();
+static Result<void> do_bootchart_stop() {
+    if (!g_bootcharting_thread) return {};
 
     // Tell the worker thread it's time to quit.
     {
@@ -190,10 +190,10 @@
     g_bootcharting_thread->join();
     delete g_bootcharting_thread;
     g_bootcharting_thread = nullptr;
-    return Success();
+    return {};
 }
 
-Result<Success> do_bootchart(const BuiltinArguments& args) {
+Result<void> do_bootchart(const BuiltinArguments& args) {
     if (args[1] == "start") return do_bootchart_start();
     return do_bootchart_stop();
 }
diff --git a/init/bootchart.h b/init/bootchart.h
index 05474ca..6f19aad 100644
--- a/init/bootchart.h
+++ b/init/bootchart.h
@@ -26,7 +26,7 @@
 namespace android {
 namespace init {
 
-Result<Success> do_bootchart(const BuiltinArguments& args);
+Result<void> do_bootchart(const BuiltinArguments& args);
 
 }  // namespace init
 }  // namespace android
diff --git a/init/boringssl_self_test.cpp b/init/boringssl_self_test.cpp
deleted file mode 100644
index 0408d30..0000000
--- a/init/boringssl_self_test.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-#include "boringssl_self_test.h"
-
-#include <android-base/logging.h>
-#include <cutils/android_reboot.h>
-#include <openssl/crypto.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace android {
-namespace init {
-
-Result<Success> StartBoringSslSelfTest(const BuiltinArguments&) {
-    pid_t id = fork();
-
-    if (id == 0) {
-        if (BORINGSSL_self_test() != 1) {
-            LOG(INFO) << "BoringSSL crypto self tests failed";
-
-            // This check has failed, so the device should refuse
-            // to boot. Rebooting to bootloader to wait for
-            // further action from the user.
-
-            int result = android_reboot(ANDROID_RB_RESTART2, 0,
-                                        "bootloader,boringssl-self-check-failed");
-            if (result != 0) {
-                LOG(ERROR) << "Failed to reboot into bootloader";
-            }
-        }
-
-        _exit(0);
-    } else if (id == -1) {
-        // Failed to fork, so cannot run the test. Refuse to continue.
-        PLOG(FATAL) << "Failed to fork for BoringSSL self test";
-    }
-
-    return Success();
-}
-
-}  // namespace init
-}  // namespace android
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 25f324c..64d9c59 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -16,6 +16,7 @@
 
 #include "builtins.h"
 
+#include <android/api-level.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -41,6 +42,10 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <memory>
+
+#include <ApexProperties.sysprop.h>
+#include <InitProperties.sysprop.h>
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -53,8 +58,8 @@
 #include <cutils/android_reboot.h>
 #include <fs_mgr.h>
 #include <fscrypt/fscrypt.h>
-#include <fscrypt/fscrypt_init_extensions.h>
 #include <libgsi/libgsi.h>
+#include <logwrap/logwrap.h>
 #include <selinux/android.h>
 #include <selinux/label.h>
 #include <selinux/selinux.h>
@@ -62,20 +67,27 @@
 
 #include "action_manager.h"
 #include "bootchart.h"
+#include "builtin_arguments.h"
+#include "fscrypt_init_extensions.h"
 #include "init.h"
 #include "mount_namespace.h"
 #include "parser.h"
 #include "property_service.h"
 #include "reboot.h"
 #include "rlimit_parser.h"
+#include "selabel.h"
 #include "selinux.h"
 #include "service.h"
+#include "service_list.h"
 #include "subcontext.h"
 #include "util.h"
 
 using namespace std::literals::string_literals;
 
 using android::base::Basename;
+using android::base::SetProperty;
+using android::base::StartsWith;
+using android::base::StringPrintf;
 using android::base::unique_fd;
 using android::fs_mgr::Fstab;
 using android::fs_mgr::ReadFstabFromFile;
@@ -85,16 +97,55 @@
 namespace android {
 namespace init {
 
+// There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
+// device, such as '/sys/class/leds/jogball-backlight/brightness'.  As of this writing, there
+// are 81 such failures on cuttlefish.  Instead of spamming the log reporting them, we do not
+// report such failures unless we're running at the DEBUG log level.
+class ErrorIgnoreEnoent {
+  public:
+    ErrorIgnoreEnoent()
+        : ignore_error_(errno == ENOENT &&
+                        android::base::GetMinimumLogSeverity() > android::base::DEBUG) {}
+    explicit ErrorIgnoreEnoent(int errno_to_append)
+        : error_(errno_to_append),
+          ignore_error_(errno_to_append == ENOENT &&
+                        android::base::GetMinimumLogSeverity() > android::base::DEBUG) {}
+
+    template <typename T>
+    operator android::base::expected<T, ResultError>() {
+        if (ignore_error_) {
+            return {};
+        }
+        return error_;
+    }
+
+    template <typename T>
+    ErrorIgnoreEnoent& operator<<(T&& t) {
+        error_ << t;
+        return *this;
+    }
+
+  private:
+    Error error_;
+    bool ignore_error_;
+};
+
+inline ErrorIgnoreEnoent ErrnoErrorIgnoreEnoent() {
+    return ErrorIgnoreEnoent(errno);
+}
+
+std::vector<std::string> late_import_paths;
+
 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
 
-static Result<Success> reboot_into_recovery(const std::vector<std::string>& options) {
+static Result<void> reboot_into_recovery(const std::vector<std::string>& options) {
     LOG(ERROR) << "Rebooting into recovery";
     std::string err;
     if (!write_bootloader_message(options, &err)) {
         return Error() << "Failed to set bootloader message: " << err;
     }
-    property_set("sys.powerctl", "reboot,recovery");
-    return Success();
+    trigger_shutdown("reboot,recovery");
+    return {};
 }
 
 template <typename F>
@@ -104,10 +155,10 @@
     }
 }
 
-static Result<Success> do_class_start(const BuiltinArguments& args) {
+static Result<void> do_class_start(const BuiltinArguments& args) {
     // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1.
     if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
-        return Success();
+        return {};
     // Starting a class does not start services which are explicitly disabled.
     // They must  be started individually.
     for (const auto& service : ServiceList::GetInstance()) {
@@ -118,13 +169,20 @@
             }
         }
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_class_start_post_data(const BuiltinArguments& args) {
+static Result<void> do_class_start_post_data(const BuiltinArguments& args) {
     if (args.context != kInitContext) {
         return Error() << "command 'class_start_post_data' only available in init context";
     }
+    static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+
+    if (!is_apex_updatable) {
+        // No need to start these on devices that don't support APEX, since they're not
+        // stopped either.
+        return {};
+    }
     for (const auto& service : ServiceList::GetInstance()) {
         if (service->classnames().count(args[1])) {
             if (auto result = service->StartIfPostData(); !result) {
@@ -133,43 +191,48 @@
             }
         }
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_class_stop(const BuiltinArguments& args) {
+static Result<void> do_class_stop(const BuiltinArguments& args) {
     ForEachServiceInClass(args[1], &Service::Stop);
-    return Success();
+    return {};
 }
 
-static Result<Success> do_class_reset(const BuiltinArguments& args) {
+static Result<void> do_class_reset(const BuiltinArguments& args) {
     ForEachServiceInClass(args[1], &Service::Reset);
-    return Success();
+    return {};
 }
 
-static Result<Success> do_class_reset_post_data(const BuiltinArguments& args) {
+static Result<void> do_class_reset_post_data(const BuiltinArguments& args) {
     if (args.context != kInitContext) {
         return Error() << "command 'class_reset_post_data' only available in init context";
     }
+    static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+    if (!is_apex_updatable) {
+        // No need to stop these on devices that don't support APEX.
+        return {};
+    }
     ForEachServiceInClass(args[1], &Service::ResetIfPostData);
-    return Success();
+    return {};
 }
 
-static Result<Success> do_class_restart(const BuiltinArguments& args) {
+static Result<void> do_class_restart(const BuiltinArguments& args) {
     // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1.
     if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
-        return Success();
+        return {};
     ForEachServiceInClass(args[1], &Service::Restart);
-    return Success();
+    return {};
 }
 
-static Result<Success> do_domainname(const BuiltinArguments& args) {
+static Result<void> do_domainname(const BuiltinArguments& args) {
     if (auto result = WriteFile("/proc/sys/kernel/domainname", args[1]); !result) {
         return Error() << "Unable to write to /proc/sys/kernel/domainname: " << result.error();
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_enable(const BuiltinArguments& args) {
+static Result<void> do_enable(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "Could not find service";
 
@@ -177,36 +240,36 @@
         return Error() << "Could not enable service: " << result.error();
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_exec(const BuiltinArguments& args) {
+static Result<void> do_exec(const BuiltinArguments& args) {
     auto service = Service::MakeTemporaryOneshotService(args.args);
     if (!service) {
-        return Error() << "Could not create exec service";
+        return Error() << "Could not create exec service: " << service.error();
     }
-    if (auto result = service->ExecStart(); !result) {
+    if (auto result = (*service)->ExecStart(); !result) {
         return Error() << "Could not start exec service: " << result.error();
     }
 
-    ServiceList::GetInstance().AddService(std::move(service));
-    return Success();
+    ServiceList::GetInstance().AddService(std::move(*service));
+    return {};
 }
 
-static Result<Success> do_exec_background(const BuiltinArguments& args) {
+static Result<void> do_exec_background(const BuiltinArguments& args) {
     auto service = Service::MakeTemporaryOneshotService(args.args);
     if (!service) {
-        return Error() << "Could not create exec background service";
+        return Error() << "Could not create exec background service: " << service.error();
     }
-    if (auto result = service->Start(); !result) {
+    if (auto result = (*service)->Start(); !result) {
         return Error() << "Could not start exec background service: " << result.error();
     }
 
-    ServiceList::GetInstance().AddService(std::move(service));
-    return Success();
+    ServiceList::GetInstance().AddService(std::move(*service));
+    return {};
 }
 
-static Result<Success> do_exec_start(const BuiltinArguments& args) {
+static Result<void> do_exec_start(const BuiltinArguments& args) {
     Service* service = ServiceList::GetInstance().FindService(args[1]);
     if (!service) {
         return Error() << "Service not found";
@@ -216,29 +279,29 @@
         return Error() << "Could not start exec service: " << result.error();
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_export(const BuiltinArguments& args) {
+static Result<void> do_export(const BuiltinArguments& args) {
     if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) {
         return ErrnoError() << "setenv() failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_hostname(const BuiltinArguments& args) {
+static Result<void> do_hostname(const BuiltinArguments& args) {
     if (auto result = WriteFile("/proc/sys/kernel/hostname", args[1]); !result) {
         return Error() << "Unable to write to /proc/sys/kernel/hostname: " << result.error();
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_ifup(const BuiltinArguments& args) {
+static Result<void> do_ifup(const BuiltinArguments& args) {
     struct ifreq ifr;
 
     strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ);
 
-    unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM, 0)));
+    unique_fd s(TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)));
     if (s < 0) return ErrnoError() << "opening socket failed";
 
     if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
@@ -251,10 +314,10 @@
         return ErrnoError() << "ioctl(..., SIOCSIFFLAGS, ...) failed";
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_insmod(const BuiltinArguments& args) {
+static Result<void> do_insmod(const BuiltinArguments& args) {
     int flags = 0;
     auto it = args.begin() + 1;
 
@@ -272,91 +335,93 @@
     int rc = syscall(__NR_finit_module, fd.get(), options.c_str(), flags);
     if (rc == -1) return ErrnoError() << "finit_module for \"" << filename << "\" failed";
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_interface_restart(const BuiltinArguments& args) {
+static Result<void> do_interface_restart(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
     if (!svc) return Error() << "interface " << args[1] << " not found";
     svc->Restart();
-    return Success();
+    return {};
 }
 
-static Result<Success> do_interface_start(const BuiltinArguments& args) {
+static Result<void> do_interface_start(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
     if (!svc) return Error() << "interface " << args[1] << " not found";
     if (auto result = svc->Start(); !result) {
         return Error() << "Could not start interface: " << result.error();
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_interface_stop(const BuiltinArguments& args) {
+static Result<void> do_interface_stop(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
     if (!svc) return Error() << "interface " << args[1] << " not found";
     svc->Stop();
-    return Success();
+    return {};
 }
 
-// mkdir <path> [mode] [owner] [group]
-static Result<Success> do_mkdir(const BuiltinArguments& args) {
-    mode_t mode = 0755;
-    if (args.size() >= 3) {
-        mode = std::strtoul(args[2].c_str(), 0, 8);
+static Result<void> make_dir_with_options(const MkdirOptions& options) {
+    std::string ref_basename;
+    if (options.ref_option == "ref") {
+        ref_basename = fscrypt_key_ref;
+    } else if (options.ref_option == "per_boot_ref") {
+        ref_basename = fscrypt_key_per_boot_ref;
+    } else {
+        return Error() << "Unknown key option: '" << options.ref_option << "'";
     }
 
-    if (!make_dir(args[1], mode)) {
-        /* chmod in case the directory already exists */
-        if (errno == EEXIST) {
-            if (fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) {
-                return ErrnoError() << "fchmodat() failed";
-            }
-        } else {
-            return ErrnoError() << "mkdir() failed";
+    struct stat mstat;
+    if (lstat(options.target.c_str(), &mstat) != 0) {
+        if (errno != ENOENT) {
+            return ErrnoError() << "lstat() failed on " << options.target;
+        }
+        if (!make_dir(options.target, options.mode)) {
+            return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << options.target;
+        }
+        if (lstat(options.target.c_str(), &mstat) != 0) {
+            return ErrnoError() << "lstat() failed on new " << options.target;
         }
     }
-
-    if (args.size() >= 4) {
-        auto uid = DecodeUid(args[3]);
-        if (!uid) {
-            return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error();
+    if (!S_ISDIR(mstat.st_mode)) {
+        return Error() << "Not a directory on " << options.target;
+    }
+    bool needs_chmod = (mstat.st_mode & ~S_IFMT) != options.mode;
+    if ((options.uid != static_cast<uid_t>(-1) && options.uid != mstat.st_uid) ||
+        (options.gid != static_cast<gid_t>(-1) && options.gid != mstat.st_gid)) {
+        if (lchown(options.target.c_str(), options.uid, options.gid) == -1) {
+            return ErrnoError() << "lchown failed on " << options.target;
         }
-        Result<gid_t> gid = -1;
-
-        if (args.size() == 5) {
-            gid = DecodeUid(args[4]);
-            if (!gid) {
-                return Error() << "Unable to decode GID for '" << args[3] << "': " << gid.error();
-            }
-        }
-
-        if (lchown(args[1].c_str(), *uid, *gid) == -1) {
-            return ErrnoError() << "lchown failed";
-        }
-
-        /* chown may have cleared S_ISUID and S_ISGID, chmod again */
-        if (mode & (S_ISUID | S_ISGID)) {
-            if (fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) {
-                return ErrnoError() << "fchmodat failed";
-            }
+        // chown may have cleared S_ISUID and S_ISGID, chmod again
+        needs_chmod = true;
+    }
+    if (needs_chmod) {
+        if (fchmodat(AT_FDCWD, options.target.c_str(), options.mode, AT_SYMLINK_NOFOLLOW) == -1) {
+            return ErrnoError() << "fchmodat() failed on " << options.target;
         }
     }
-
     if (fscrypt_is_native()) {
-        if (fscrypt_set_directory_policy(args[1].c_str())) {
+        if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) {
             return reboot_into_recovery(
-                {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]});
+                    {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target});
         }
     }
-    return Success();
+    return {};
+}
+
+// mkdir <path> [mode] [owner] [group] [<option> ...]
+static Result<void> do_mkdir(const BuiltinArguments& args) {
+    auto options = ParseMkdir(args.args);
+    if (!options) return options.error();
+    return make_dir_with_options(*options);
 }
 
 /* umount <path> */
-static Result<Success> do_umount(const BuiltinArguments& args) {
+static Result<void> do_umount(const BuiltinArguments& args) {
     if (umount(args[1].c_str()) < 0) {
         return ErrnoError() << "umount() failed";
     }
-    return Success();
+    return {};
 }
 
 static struct {
@@ -384,7 +449,7 @@
 #define DATA_MNT_POINT "/data"
 
 /* mount <type> <device> <path> <flags ...> <options> */
-static Result<Success> do_mount(const BuiltinArguments& args) {
+static Result<void> do_mount(const BuiltinArguments& args) {
     const char* options = nullptr;
     unsigned flags = 0;
     bool wait = false;
@@ -431,7 +496,7 @@
                         ioctl(loop, LOOP_CLR_FD, 0);
                         return ErrnoError() << "mount() failed";
                     }
-                    return Success();
+                    return {};
                 }
             }
         }
@@ -441,12 +506,12 @@
         if (wait)
             wait_for_file(source, kCommandRetryTimeout);
         if (mount(source, target, system, flags, options) < 0) {
-            return ErrnoError() << "mount() failed";
+            return ErrnoErrorIgnoreEnoent() << "mount() failed";
         }
 
     }
 
-    return Success();
+    return {};
 }
 
 /* Imports .rc files from the specified paths. Default ones are applied if none is given.
@@ -474,78 +539,6 @@
     if (false) DumpState();
 }
 
-/* handle_fstab
- *
- *  Read the given fstab file and execute func on it.
- */
-static Result<int> handle_fstab(const std::string& fstabfile, std::function<int(Fstab*)> func) {
-    /*
-     * Call fs_mgr_[u]mount_all() to [u]mount all filesystems.  We fork(2) and
-     * do the call in the child to provide protection to the main init
-     * process if anything goes wrong (crash or memory leak), and wait for
-     * the child to finish in the parent.
-     */
-    pid_t pid = fork();
-    if (pid > 0) {
-        /* Parent.  Wait for the child to return */
-        int status;
-        int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
-        if (wp_ret == -1) {
-            // Unexpected error code. We will continue anyway.
-            PLOG(WARNING) << "waitpid failed";
-        }
-
-        if (WIFEXITED(status)) {
-            return WEXITSTATUS(status);
-        } else {
-            return Error() << "child aborted";
-        }
-    } else if (pid == 0) {
-        /* child, call fs_mgr_[u]mount_all() */
-
-        // So we can always see what fs_mgr_[u]mount_all() does.
-        // Only needed if someone explicitly changes the default log level in their init.rc.
-        android::base::ScopedLogSeverity info(android::base::INFO);
-
-        Fstab fstab;
-        ReadFstabFromFile(fstabfile, &fstab);
-
-        int child_ret = func(&fstab);
-
-        _exit(child_ret);
-    } else {
-        return Error() << "fork() failed";
-    }
-}
-
-/* mount_fstab
- *
- *  Call fs_mgr_mount_all() to mount the given fstab
- */
-static Result<int> mount_fstab(const std::string& fstabfile, int mount_mode) {
-    return handle_fstab(fstabfile, [mount_mode](Fstab* fstab) {
-        int ret = fs_mgr_mount_all(fstab, mount_mode);
-        if (ret == -1) {
-            PLOG(ERROR) << "fs_mgr_mount_all returned an error";
-        }
-        return ret;
-    });
-}
-
-/* umount_fstab
- *
- *  Call fs_mgr_umount_all() to umount the given fstab
- */
-static Result<int> umount_fstab(const std::string& fstabfile) {
-    return handle_fstab(fstabfile, [](Fstab* fstab) {
-        int ret = fs_mgr_umount_all(fstab);
-        if (ret != 0) {
-            PLOG(ERROR) << "fs_mgr_umount_all returned " << ret;
-        }
-        return ret;
-    });
-}
-
 /* Queue event based on fs_mgr return code.
  *
  * code: return code of fs_mgr_mount_all
@@ -555,23 +548,37 @@
  *
  * return code is processed based on input code
  */
-static Result<Success> queue_fs_event(int code) {
+static Result<void> queue_fs_event(int code, bool userdata_remount) {
     if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
+        if (userdata_remount) {
+            // FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION should only happen on FDE devices. Since we don't
+            // support userdata remount on FDE devices, this should never been triggered. Time to
+            // panic!
+            LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
+            trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
+        }
         ActionManager::GetInstance().QueueEventTrigger("encrypt");
-        return Success();
+        return {};
     } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
-        property_set("ro.crypto.state", "encrypted");
-        property_set("ro.crypto.type", "block");
+        if (userdata_remount) {
+            // FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED should only happen on FDE devices. Since we
+            // don't support userdata remount on FDE devices, this should never been triggered.
+            // Time to panic!
+            LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
+            trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
+        }
+        SetProperty("ro.crypto.state", "encrypted");
+        SetProperty("ro.crypto.type", "block");
         ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
-        return Success();
+        return {};
     } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
-        property_set("ro.crypto.state", "unencrypted");
+        SetProperty("ro.crypto.state", "unencrypted");
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-        return Success();
+        return {};
     } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
-        property_set("ro.crypto.state", "unsupported");
+        SetProperty("ro.crypto.state", "unsupported");
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-        return Success();
+        return {};
     } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
         /* Setup a wipe via recovery, and reboot into recovery */
         if (android::gsi::IsGsiRunning()) {
@@ -582,38 +589,38 @@
         return reboot_into_recovery(options);
         /* If reboot worked, there is no return. */
     } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
-        if (fscrypt_install_keyring()) {
-            return Error() << "fscrypt_install_keyring() failed";
+        if (!FscryptInstallKeyring()) {
+            return Error() << "FscryptInstallKeyring() failed";
         }
-        property_set("ro.crypto.state", "encrypted");
-        property_set("ro.crypto.type", "file");
+        SetProperty("ro.crypto.state", "encrypted");
+        SetProperty("ro.crypto.type", "file");
 
         // Although encrypted, we have device key, so we do not need to
         // do anything different from the nonencrypted case.
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-        return Success();
+        return {};
     } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
-        if (fscrypt_install_keyring()) {
-            return Error() << "fscrypt_install_keyring() failed";
+        if (!FscryptInstallKeyring()) {
+            return Error() << "FscryptInstallKeyring() failed";
         }
-        property_set("ro.crypto.state", "encrypted");
-        property_set("ro.crypto.type", "file");
+        SetProperty("ro.crypto.state", "encrypted");
+        SetProperty("ro.crypto.type", "file");
 
         // Although encrypted, vold has already set the device up, so we do not need to
         // do anything different from the nonencrypted case.
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-        return Success();
+        return {};
     } else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
-        if (fscrypt_install_keyring()) {
-            return Error() << "fscrypt_install_keyring() failed";
+        if (!FscryptInstallKeyring()) {
+            return Error() << "FscryptInstallKeyring() failed";
         }
-        property_set("ro.crypto.state", "encrypted");
-        property_set("ro.crypto.type", "file");
+        SetProperty("ro.crypto.state", "encrypted");
+        SetProperty("ro.crypto.type", "file");
 
         // Although encrypted, vold has already set the device up, so we do not need to
         // do anything different from the nonencrypted case.
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
-        return Success();
+        return {};
     } else if (code > 0) {
         Error() << "fs_mgr_mount_all() returned unexpected error " << code;
     }
@@ -622,17 +629,19 @@
     return Error() << "Invalid code: " << code;
 }
 
+static int initial_mount_fstab_return_code = -1;
+
 /* mount_all <fstab> [ <path> ]* [--<options>]*
  *
  * This function might request a reboot, in which case it will
  * not return.
  */
-static Result<Success> do_mount_all(const BuiltinArguments& args) {
+static Result<void> do_mount_all(const BuiltinArguments& args) {
     std::size_t na = 0;
     bool import_rc = true;
     bool queue_event = true;
     int mount_mode = MOUNT_MODE_DEFAULT;
-    const auto& fstabfile = args[1];
+    const auto& fstab_file = args[1];
     std::size_t path_arg_end = args.size();
     const char* prop_post_fix = "default";
 
@@ -652,13 +661,16 @@
 
     std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
     android::base::Timer t;
-    auto mount_fstab_return_code = mount_fstab(fstabfile, mount_mode);
-    if (!mount_fstab_return_code) {
-        return Error() << "mount_fstab() failed " << mount_fstab_return_code.error();
-    }
-    property_set(prop_name, std::to_string(t.duration().count()));
 
-    if (import_rc) {
+    Fstab fstab;
+    if (!ReadFstabFromFile(fstab_file, &fstab)) {
+        return Error() << "Could not read fstab";
+    }
+
+    auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode);
+    SetProperty(prop_name, std::to_string(t.duration().count()));
+
+    if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
         /* Paths of .rc files are specified at the 2nd argument and beyond */
         import_late(args.args, 2, path_arg_end);
     }
@@ -666,25 +678,30 @@
     if (queue_event) {
         /* queue_fs_event will queue event based on mount_fstab return code
          * and return processed return code*/
-        auto queue_fs_result = queue_fs_event(*mount_fstab_return_code);
+        initial_mount_fstab_return_code = mount_fstab_return_code;
+        auto queue_fs_result = queue_fs_event(mount_fstab_return_code, false);
         if (!queue_fs_result) {
             return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
         }
     }
 
-    return Success();
+    return {};
 }
 
 /* umount_all <fstab> */
-static Result<Success> do_umount_all(const BuiltinArguments& args) {
-    auto umount_fstab_return_code = umount_fstab(args[1]);
-    if (!umount_fstab_return_code) {
-        return Error() << "umount_fstab() failed " << umount_fstab_return_code.error();
+static Result<void> do_umount_all(const BuiltinArguments& args) {
+    Fstab fstab;
+    if (!ReadFstabFromFile(args[1], &fstab)) {
+        return Error() << "Could not read fstab";
     }
-    return Success();
+
+    if (auto result = fs_mgr_umount_all(&fstab); result != 0) {
+        return Error() << "umount_fstab() failed " << result;
+    }
+    return {};
 }
 
-static Result<Success> do_swapon_all(const BuiltinArguments& args) {
+static Result<void> do_swapon_all(const BuiltinArguments& args) {
     Fstab fstab;
     if (!ReadFstabFromFile(args[1], &fstab)) {
         return Error() << "Could not read fstab '" << args[1] << "'";
@@ -694,50 +711,59 @@
         return Error() << "fs_mgr_swapon_all() failed";
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_setprop(const BuiltinArguments& args) {
-    property_set(args[1], args[2]);
-    return Success();
+static Result<void> do_setprop(const BuiltinArguments& args) {
+    if (StartsWith(args[1], "ctl.")) {
+        return Error()
+               << "Cannot set ctl. properties from init; call the Service functions directly";
+    }
+    if (args[1] == kRestoreconProperty) {
+        return Error() << "Cannot set '" << kRestoreconProperty
+                       << "' from init; use the restorecon builtin directly";
+    }
+
+    SetProperty(args[1], args[2]);
+    return {};
 }
 
-static Result<Success> do_setrlimit(const BuiltinArguments& args) {
+static Result<void> do_setrlimit(const BuiltinArguments& args) {
     auto rlimit = ParseRlimit(args.args);
     if (!rlimit) return rlimit.error();
 
     if (setrlimit(rlimit->first, &rlimit->second) == -1) {
         return ErrnoError() << "setrlimit failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_start(const BuiltinArguments& args) {
+static Result<void> do_start(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     if (auto result = svc->Start(); !result) {
-        return Error() << "Could not start service: " << result.error();
+        return ErrorIgnoreEnoent() << "Could not start service: " << result.error();
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_stop(const BuiltinArguments& args) {
+static Result<void> do_stop(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     svc->Stop();
-    return Success();
+    return {};
 }
 
-static Result<Success> do_restart(const BuiltinArguments& args) {
+static Result<void> do_restart(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     svc->Restart();
-    return Success();
+    return {};
 }
 
-static Result<Success> do_trigger(const BuiltinArguments& args) {
+static Result<void> do_trigger(const BuiltinArguments& args) {
     ActionManager::GetInstance().QueueEventTrigger(args[1]);
-    return Success();
+    return {};
 }
 
 static int MakeSymlink(const std::string& target, const std::string& linkpath) {
@@ -758,33 +784,30 @@
     return rc;
 }
 
-static Result<Success> do_symlink(const BuiltinArguments& args) {
+static Result<void> do_symlink(const BuiltinArguments& args) {
     if (MakeSymlink(args[1], args[2]) < 0) {
         // The symlink builtin is often used to create symlinks for older devices to be backwards
         // compatible with new paths, therefore we skip reporting this error.
-        if (errno == EEXIST && android::base::GetMinimumLogSeverity() > android::base::DEBUG) {
-            return Success();
-        }
-        return ErrnoError() << "symlink() failed";
+        return ErrnoErrorIgnoreEnoent() << "symlink() failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_rm(const BuiltinArguments& args) {
+static Result<void> do_rm(const BuiltinArguments& args) {
     if (unlink(args[1].c_str()) < 0) {
         return ErrnoError() << "unlink() failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_rmdir(const BuiltinArguments& args) {
+static Result<void> do_rmdir(const BuiltinArguments& args) {
     if (rmdir(args[1].c_str()) < 0) {
         return ErrnoError() << "rmdir() failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_sysclktz(const BuiltinArguments& args) {
+static Result<void> do_sysclktz(const BuiltinArguments& args) {
     struct timezone tz = {};
     if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
         return Error() << "Unable to parse mins_west_of_gmt";
@@ -793,21 +816,10 @@
     if (settimeofday(nullptr, &tz) == -1) {
         return ErrnoError() << "settimeofday() failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_verity_load_state(const BuiltinArguments& args) {
-    int mode = -1;
-    bool loaded = fs_mgr_load_verity_state(&mode);
-    if (loaded && mode != VERITY_MODE_DEFAULT) {
-        ActionManager::GetInstance().QueueEventTrigger("verity-logging");
-    }
-    if (!loaded) return Error() << "Could not load verity state";
-
-    return Success();
-}
-
-static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
+static Result<void> do_verity_update_state(const BuiltinArguments& args) {
     int mode;
     if (!fs_mgr_load_verity_state(&mode)) {
         return Error() << "fs_mgr_load_verity_state() failed";
@@ -826,22 +838,23 @@
         // To be consistent in vboot 1.0 and vboot 2.0 (AVB), use "system" for the partition even
         // for system as root, so it has property [partition.system.verified].
         std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
-        property_set("partition." + partition + ".verified", std::to_string(mode));
+        SetProperty("partition." + partition + ".verified", std::to_string(mode));
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_write(const BuiltinArguments& args) {
+static Result<void> do_write(const BuiltinArguments& args) {
     if (auto result = WriteFile(args[1], args[2]); !result) {
-        return Error() << "Unable to write to file '" << args[1] << "': " << result.error();
+        return ErrorIgnoreEnoent()
+               << "Unable to write to file '" << args[1] << "': " << result.error();
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> readahead_file(const std::string& filename, bool fully) {
-    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY)));
+static Result<void> readahead_file(const std::string& filename, bool fully) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY | O_CLOEXEC)));
     if (fd == -1) {
         return ErrnoError() << "Error opening file";
     }
@@ -860,10 +873,10 @@
             return ErrnoError() << "Error reading file";
         }
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_readahead(const BuiltinArguments& args) {
+static Result<void> do_readahead(const BuiltinArguments& args) {
     struct stat sb;
 
     if (stat(args[1].c_str(), &sb)) {
@@ -919,10 +932,10 @@
     } else if (pid < 0) {
         return ErrnoError() << "Fork failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_copy(const BuiltinArguments& args) {
+static Result<void> do_copy(const BuiltinArguments& args) {
     auto file_contents = ReadFile(args[1]);
     if (!file_contents) {
         return Error() << "Could not read input file '" << args[1] << "': " << file_contents.error();
@@ -931,10 +944,10 @@
         return Error() << "Could not write to output file '" << args[2] << "': " << result.error();
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_chown(const BuiltinArguments& args) {
+static Result<void> do_chown(const BuiltinArguments& args) {
     auto uid = DecodeUid(args[1]);
     if (!uid) {
         return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
@@ -952,10 +965,10 @@
     }
 
     if (lchown(path.c_str(), *uid, *gid) == -1) {
-        return ErrnoError() << "lchown() failed";
+        return ErrnoErrorIgnoreEnoent() << "lchown() failed";
     }
 
-    return Success();
+    return {};
 }
 
 static mode_t get_mode(const char *s) {
@@ -971,63 +984,40 @@
     return mode;
 }
 
-static Result<Success> do_chmod(const BuiltinArguments& args) {
+static Result<void> do_chmod(const BuiltinArguments& args) {
     mode_t mode = get_mode(args[1].c_str());
     if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
-        return ErrnoError() << "fchmodat() failed";
+        return ErrnoErrorIgnoreEnoent() << "fchmodat() failed";
     }
-    return Success();
+    return {};
 }
 
-static Result<Success> do_restorecon(const BuiltinArguments& args) {
+static Result<void> do_restorecon(const BuiltinArguments& args) {
+    auto restorecon_info = ParseRestorecon(args.args);
+    if (!restorecon_info) {
+        return restorecon_info.error();
+    }
+
+    const auto& [flag, paths] = *restorecon_info;
+
     int ret = 0;
-
-    struct flag_type {const char* name; int value;};
-    static const flag_type flags[] = {
-        {"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE},
-        {"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE},
-        {"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS},
-        {0, 0}
-    };
-
-    int flag = 0;
-
-    bool in_flags = true;
-    for (size_t i = 1; i < args.size(); ++i) {
-        if (android::base::StartsWith(args[i], "--")) {
-            if (!in_flags) {
-                return Error() << "flags must precede paths";
-            }
-            bool found = false;
-            for (size_t j = 0; flags[j].name; ++j) {
-                if (args[i] == flags[j].name) {
-                    flag |= flags[j].value;
-                    found = true;
-                    break;
-                }
-            }
-            if (!found) {
-                return Error() << "bad flag " << args[i];
-            }
-        } else {
-            in_flags = false;
-            if (selinux_android_restorecon(args[i].c_str(), flag) < 0) {
-                ret = errno;
-            }
+    for (const auto& path : paths) {
+        if (selinux_android_restorecon(path.c_str(), flag) < 0) {
+            ret = errno;
         }
     }
 
-    if (ret) return ErrnoError() << "selinux_android_restorecon() failed";
-    return Success();
+    if (ret) return ErrnoErrorIgnoreEnoent() << "selinux_android_restorecon() failed";
+    return {};
 }
 
-static Result<Success> do_restorecon_recursive(const BuiltinArguments& args) {
+static Result<void> do_restorecon_recursive(const BuiltinArguments& args) {
     std::vector<std::string> non_const_args(args.args);
     non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
     return do_restorecon({std::move(non_const_args), args.context});
 }
 
-static Result<Success> do_loglevel(const BuiltinArguments& args) {
+static Result<void> do_loglevel(const BuiltinArguments& args) {
     // TODO: support names instead/as well?
     int log_level = -1;
     android::base::ParseInt(args[1], &log_level);
@@ -1045,20 +1035,33 @@
             return Error() << "invalid log level " << log_level;
     }
     android::base::SetMinimumLogSeverity(severity);
-    return Success();
+    return {};
 }
 
-static Result<Success> do_load_persist_props(const BuiltinArguments& args) {
-    load_persist_props();
-    return Success();
+static Result<void> do_load_persist_props(const BuiltinArguments& args) {
+    // Devices with FDE have load_persist_props called twice; the first time when the temporary
+    // /data partition is mounted and then again once /data is truly mounted.  We do not want to
+    // read persistent properties from the temporary /data partition or mark persistent properties
+    // as having been loaded during the first call, so we return in that case.
+    std::string crypto_state = android::base::GetProperty("ro.crypto.state", "");
+    std::string crypto_type = android::base::GetProperty("ro.crypto.type", "");
+    if (crypto_state == "encrypted" && crypto_type == "block") {
+        static size_t num_calls = 0;
+        if (++num_calls == 1) return {};
+    }
+
+    SendLoadPersistentPropertiesMessage();
+
+    start_waiting_for_property("ro.persistent_properties.ready", "true");
+    return {};
 }
 
-static Result<Success> do_load_system_props(const BuiltinArguments& args) {
+static Result<void> do_load_system_props(const BuiltinArguments& args) {
     LOG(INFO) << "deprecated action `load_system_props` called.";
-    return Success();
+    return {};
 }
 
-static Result<Success> do_wait(const BuiltinArguments& args) {
+static Result<void> do_wait(const BuiltinArguments& args) {
     auto timeout = kCommandRetryTimeout;
     if (args.size() == 3) {
         int timeout_int;
@@ -1072,10 +1075,10 @@
         return Error() << "wait_for_file() failed";
     }
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
+static Result<void> do_wait_for_prop(const BuiltinArguments& args) {
     const char* name = args[1].c_str();
     const char* value = args[2].c_str();
     size_t value_len = strlen(value);
@@ -1089,80 +1092,142 @@
     if (!start_waiting_for_property(name, value)) {
         return Error() << "already waiting for a property";
     }
-    return Success();
+    return {};
 }
 
 static bool is_file_crypto() {
     return android::base::GetProperty("ro.crypto.type", "") == "file";
 }
 
-static Result<Success> ExecWithRebootOnFailure(const std::string& reboot_reason,
-                                               const BuiltinArguments& args) {
-    auto service = Service::MakeTemporaryOneshotService(args.args);
+static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& args,
+                                              std::function<void(const std::string&)> function) {
+    auto service = Service::MakeTemporaryOneshotService(args);
     if (!service) {
-        return Error() << "Could not create exec service";
+        function("MakeTemporaryOneshotService failed: " + service.error().message());
     }
-    service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
+    (*service)->AddReapCallback([function](const siginfo_t& siginfo) {
         if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
-            // TODO (b/122850122): support this in gsi
-            if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
-                LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
-                if (auto result = reboot_into_recovery(
-                            {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
-                    !result) {
-                    LOG(FATAL) << "Could not reboot into recovery: " << result.error();
-                }
-            } else {
-                LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
-            }
+            function(StringPrintf("Exec service failed, status %d", siginfo.si_status));
         }
     });
-    if (auto result = service->ExecStart(); !result) {
-        return Error() << "Could not start exec service: " << result.error();
+    if (auto result = (*service)->ExecStart(); !result) {
+        function("ExecStart failed: " + result.error().message());
     }
-    ServiceList::GetInstance().AddService(std::move(service));
-    return Success();
+    ServiceList::GetInstance().AddService(std::move(*service));
+    return {};
 }
 
-static Result<Success> do_installkey(const BuiltinArguments& args) {
-    if (!is_file_crypto()) return Success();
+static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) {
+    auto reboot_reason = vdc_arg + "_failed";
+
+    auto reboot = [reboot_reason](const std::string& message) {
+        // TODO (b/122850122): support this in gsi
+        if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
+            LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason;
+            if (auto result = reboot_into_recovery(
+                        {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
+                !result) {
+                LOG(FATAL) << "Could not reboot into recovery: " << result.error();
+            }
+        } else {
+            LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
+        }
+    };
+
+    std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg};
+    return ExecWithFunctionOnFailure(args, reboot);
+}
+
+static Result<void> do_remount_userdata(const BuiltinArguments& args) {
+    if (initial_mount_fstab_return_code == -1) {
+        return Error() << "Calling remount_userdata too early";
+    }
+    Fstab fstab;
+    if (!ReadDefaultFstab(&fstab)) {
+        // TODO(b/135984674): should we reboot here?
+        return Error() << "Failed to read fstab";
+    }
+    // TODO(b/135984674): check that fstab contains /data.
+    if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) {
+        trigger_shutdown("reboot,mount-userdata-failed");
+    }
+    if (auto result = queue_fs_event(initial_mount_fstab_return_code, true); !result) {
+        return Error() << "queue_fs_event() failed: " << result.error();
+    }
+    return {};
+}
+
+static Result<void> do_installkey(const BuiltinArguments& args) {
+    if (!is_file_crypto()) return {};
 
     auto unencrypted_dir = args[1] + fscrypt_unencrypted_folder;
     if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
         return ErrnoError() << "Failed to create " << unencrypted_dir;
     }
-    return ExecWithRebootOnFailure(
-        "enablefilecrypto_failed",
-        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}, args.context});
+    return ExecVdcRebootOnFailure("enablefilecrypto");
 }
 
-static Result<Success> do_init_user0(const BuiltinArguments& args) {
-    return ExecWithRebootOnFailure(
-        "init_user0_failed",
-        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
+static Result<void> do_init_user0(const BuiltinArguments& args) {
+    return ExecVdcRebootOnFailure("init_user0");
 }
 
-static Result<Success> do_mark_post_data(const BuiltinArguments& args) {
+static Result<void> do_mark_post_data(const BuiltinArguments& args) {
     ServiceList::GetInstance().MarkPostData();
 
-    return Success();
+    return {};
 }
 
-static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
+static Result<void> GenerateLinkerConfiguration() {
+    const char* linkerconfig_binary = "/system/bin/linkerconfig";
+    const char* linkerconfig_target = "/linkerconfig";
+    const char* arguments[] = {linkerconfig_binary, "--target", linkerconfig_target};
+
+    if (logwrap_fork_execvp(arraysize(arguments), arguments, nullptr, false, LOG_KLOG, false,
+                            nullptr) != 0) {
+        return ErrnoError() << "failed to execute linkerconfig";
+    }
+
+    LOG(INFO) << "linkerconfig generated " << linkerconfig_target
+              << " with mounted APEX modules info";
+
+    return {};
+}
+
+static bool IsApexUpdatable() {
+    static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+    return updatable;
+}
+
+static Result<void> do_update_linker_config(const BuiltinArguments&) {
+    // If APEX is not updatable, then all APEX information are already included in the first
+    // linker config generation, so there is no need to update linker configuration again.
+    if (IsApexUpdatable()) {
+        return GenerateLinkerConfiguration();
+    }
+
+    return {};
+}
+
+static Result<void> parse_apex_configs() {
     glob_t glob_result;
-    // @ is added to filter out the later paths, which are bind mounts of the places
-    // where the APEXes are really mounted at. Otherwise, we will parse the
-    // same file twice.
-    static constexpr char glob_pattern[] = "/apex/*@*/etc/*.rc";
+    static constexpr char glob_pattern[] = "/apex/*/etc/*.rc";
     const int ret = glob(glob_pattern, GLOB_MARK, nullptr, &glob_result);
     if (ret != 0 && ret != GLOB_NOMATCH) {
         globfree(&glob_result);
         return Error() << "glob pattern '" << glob_pattern << "' failed";
     }
     std::vector<std::string> configs;
-    Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance());
+    Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance(), true);
     for (size_t i = 0; i < glob_result.gl_pathc; i++) {
-        configs.emplace_back(glob_result.gl_pathv[i]);
+        std::string path = glob_result.gl_pathv[i];
+        // Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
+        // /apex/<name> paths, so unless we filter them out, we will parse the
+        // same file twice.
+        std::vector<std::string> paths = android::base::Split(path, "/");
+        if (paths.size() >= 3 && paths[2].find('@') != std::string::npos) {
+            continue;
+        }
+        configs.push_back(path);
     }
     globfree(&glob_result);
 
@@ -1176,25 +1241,81 @@
     }
     ServiceList::GetInstance().MarkServicesUpdate();
     if (success) {
-        return Success();
+        return {};
     } else {
         return Error() << "Could not parse apex configs";
     }
 }
 
-static Result<Success> do_enter_default_mount_ns(const BuiltinArguments& args) {
+/*
+ * Creates a directory under /data/misc/apexdata/ for each APEX.
+ */
+static Result<void> create_apex_data_dirs() {
+    auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
+    if (!dirp) {
+        return ErrnoError() << "Unable to open apex directory";
+    }
+    struct dirent* entry;
+    while ((entry = readdir(dirp.get())) != nullptr) {
+        if (entry->d_type != DT_DIR) continue;
+
+        const char* name = entry->d_name;
+        // skip any starting with "."
+        if (name[0] == '.') continue;
+
+        if (strchr(name, '@') != nullptr) continue;
+
+        auto path = "/data/misc/apexdata/" + std::string(name);
+        auto system_uid = DecodeUid("system");
+        auto options =
+                MkdirOptions{path, 0700, *system_uid, *system_uid, FscryptAction::kNone, "ref"};
+        make_dir_with_options(options);
+    }
+    return {};
+}
+
+static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
+    auto create_dirs = create_apex_data_dirs();
+    if (!create_dirs) {
+        return create_dirs.error();
+    }
+    auto parse_configs = parse_apex_configs();
+    if (!parse_configs) {
+        return parse_configs.error();
+    }
+
+    auto update_linker_config = do_update_linker_config(args);
+    if (!update_linker_config) {
+        return update_linker_config.error();
+    }
+
+    return {};
+}
+
+static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) {
     if (SwitchToDefaultMountNamespace()) {
-        return Success();
+        return {};
     } else {
         return Error() << "Failed to enter into default mount namespace";
     }
 }
 
+static Result<void> do_finish_userspace_reboot(const BuiltinArguments&) {
+    LOG(INFO) << "Userspace reboot successfully finished";
+    boot_clock::time_point now = boot_clock::now();
+    SetProperty("sys.init.userspace_reboot.last_finished",
+                std::to_string(now.time_since_epoch().count()));
+    if (!android::sysprop::InitProperties::userspace_reboot_in_progress(false)) {
+        return Error() << "Failed to set sys.init.userspace_reboot.in_progress property";
+    }
+    return {};
+}
+
 // Builtin-function-map start
-const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
+const BuiltinFunctionMap& GetBuiltinFunctionMap() {
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
     // clang-format off
-    static const Map builtin_functions = {
+    static const BuiltinFunctionMap builtin_functions = {
         {"bootchart",               {1,     1,    {false,  do_bootchart}}},
         {"chmod",                   {2,     2,    {true,   do_chmod}}},
         {"chown",                   {2,     3,    {true,   do_chown}}},
@@ -1211,6 +1332,7 @@
         {"exec_background",         {1,     kMax, {false,  do_exec_background}}},
         {"exec_start",              {1,     1,    {false,  do_exec_start}}},
         {"export",                  {2,     2,    {false,  do_export}}},
+        {"finish_userspace_reboot", {0,     0,    {false,  do_finish_userspace_reboot}}},
         {"hostname",                {1,     1,    {true,   do_hostname}}},
         {"ifup",                    {1,     1,    {true,   do_ifup}}},
         {"init_user0",              {0,     0,    {false,  do_init_user0}}},
@@ -1223,17 +1345,19 @@
         {"load_system_props",       {0,     0,    {false,  do_load_system_props}}},
         {"loglevel",                {1,     1,    {false,  do_loglevel}}},
         {"mark_post_data",          {0,     0,    {false,  do_mark_post_data}}},
-        {"mkdir",                   {1,     4,    {true,   do_mkdir}}},
+        {"mkdir",                   {1,     6,    {true,   do_mkdir}}},
         // TODO: Do mount operations in vendor_init.
         // mount_all is currently too complex to run in vendor_init as it queues action triggers,
         // imports rc scripts, etc.  It should be simplified and run in vendor_init context.
         // mount and umount are run in the same context as mount_all for symmetry.
         {"mount_all",               {1,     kMax, {false,  do_mount_all}}},
         {"mount",                   {3,     kMax, {false,  do_mount}}},
-        {"parse_apex_configs",      {0,     0,    {false,  do_parse_apex_configs}}},
+        {"perform_apex_config",     {0,     0,    {false,  do_perform_apex_config}}},
         {"umount",                  {1,     1,    {false,  do_umount}}},
         {"umount_all",              {1,     1,    {false,  do_umount_all}}},
+        {"update_linker_config",    {0,     0,    {false,  do_update_linker_config}}},
         {"readahead",               {1,     2,    {true,   do_readahead}}},
+        {"remount_userdata",        {0,     0,    {false,  do_remount_userdata}}},
         {"restart",                 {1,     1,    {false,  do_restart}}},
         {"restorecon",              {1,     kMax, {true,   do_restorecon}}},
         {"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},
@@ -1248,7 +1372,6 @@
         {"symlink",                 {2,     2,    {true,   do_symlink}}},
         {"sysclktz",                {1,     1,    {false,  do_sysclktz}}},
         {"trigger",                 {1,     1,    {false,  do_trigger}}},
-        {"verity_load_state",       {0,     0,    {false,  do_verity_load_state}}},
         {"verity_update_state",     {0,     0,    {false,  do_verity_update_state}}},
         {"wait",                    {1,     2,    {true,   do_wait}}},
         {"wait_for_prop",           {2,     2,    {false,  do_wait_for_prop}}},
diff --git a/init/builtins.h b/init/builtins.h
index 814b2d5..f0ff1eb 100644
--- a/init/builtins.h
+++ b/init/builtins.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_BUILTINS_H
-#define _INIT_BUILTINS_H
+#pragma once
 
 #include <functional>
 #include <map>
@@ -29,18 +28,18 @@
 namespace android {
 namespace init {
 
-using BuiltinFunction = std::function<Result<Success>(const BuiltinArguments&)>;
+using BuiltinFunction = std::function<Result<void>(const BuiltinArguments&)>;
 
-using KeywordFunctionMap = KeywordMap<std::pair<bool, BuiltinFunction>>;
-class BuiltinFunctionMap : public KeywordFunctionMap {
-  public:
-    BuiltinFunctionMap() {}
-
-  private:
-    const Map& map() const override;
+struct BuiltinFunctionMapValue {
+    bool run_in_subcontext;
+    BuiltinFunction function;
 };
 
+using BuiltinFunctionMap = KeywordMap<BuiltinFunctionMapValue>;
+
+const BuiltinFunctionMap& GetBuiltinFunctionMap();
+
+extern std::vector<std::string> late_import_paths;
+
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/check_builtins.cpp b/init/check_builtins.cpp
new file mode 100644
index 0000000..bef6966
--- /dev/null
+++ b/init/check_builtins.cpp
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+
+// Note that these check functions cannot check expanded arguments from properties, since they will
+// not know what those properties would be at runtime.  They will be passed an empty string in the
+// situation that the input line had a property expansion without a default value, since an empty
+// string is otherwise an impossible value.  They should therefore disregard checking empty
+// arguments.
+
+#include "check_builtins.h"
+
+#include <sys/time.h>
+
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+
+#include "builtin_arguments.h"
+#include "host_init_verifier.h"
+#include "interface_utils.h"
+#include "property_type.h"
+#include "rlimit_parser.h"
+#include "service.h"
+#include "util.h"
+
+using android::base::ParseInt;
+using android::base::StartsWith;
+
+#define ReturnIfAnyArgsEmpty()     \
+    for (const auto& arg : args) { \
+        if (arg.empty()) {         \
+            return {};             \
+        }                          \
+    }
+
+namespace android {
+namespace init {
+
+Result<void> check_chown(const BuiltinArguments& args) {
+    if (!args[1].empty()) {
+        auto uid = DecodeUid(args[1]);
+        if (!uid) {
+            return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
+        }
+    }
+
+    // GID is optional and pushes the index of path out by one if specified.
+    if (args.size() == 4 && !args[2].empty()) {
+        auto gid = DecodeUid(args[2]);
+        if (!gid) {
+            return Error() << "Unable to decode GID for '" << args[2] << "': " << gid.error();
+        }
+    }
+
+    return {};
+}
+
+Result<void> check_exec(const BuiltinArguments& args) {
+    ReturnIfAnyArgsEmpty();
+
+    auto result = Service::MakeTemporaryOneshotService(args.args);
+    if (!result) {
+        return result.error();
+    }
+
+    return {};
+}
+
+Result<void> check_exec_background(const BuiltinArguments& args) {
+    return check_exec(std::move(args));
+}
+
+Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
+    BuiltinArguments remaining_args(args.context);
+
+    remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
+    remaining_args.args[0] = args[0];
+
+    return check_exec(remaining_args);
+}
+
+Result<void> check_interface_restart(const BuiltinArguments& args) {
+    if (auto result = IsKnownInterface(args[1]); !result) {
+        return result.error();
+    }
+    return {};
+}
+
+Result<void> check_interface_start(const BuiltinArguments& args) {
+    return check_interface_restart(std::move(args));
+}
+
+Result<void> check_interface_stop(const BuiltinArguments& args) {
+    return check_interface_restart(std::move(args));
+}
+
+Result<void> check_load_system_props(const BuiltinArguments& args) {
+    return Error() << "'load_system_props' is deprecated";
+}
+
+Result<void> check_loglevel(const BuiltinArguments& args) {
+    ReturnIfAnyArgsEmpty();
+
+    int log_level = -1;
+    ParseInt(args[1], &log_level);
+    if (log_level < 0 || log_level > 7) {
+        return Error() << "loglevel must be in the range of 0-7";
+    }
+    return {};
+}
+
+Result<void> check_mkdir(const BuiltinArguments& args) {
+    auto options = ParseMkdir(args.args);
+    if (!options) {
+        return options.error();
+    }
+    return {};
+}
+
+Result<void> check_restorecon(const BuiltinArguments& args) {
+    ReturnIfAnyArgsEmpty();
+
+    auto restorecon_info = ParseRestorecon(args.args);
+    if (!restorecon_info) {
+        return restorecon_info.error();
+    }
+
+    return {};
+}
+
+Result<void> check_restorecon_recursive(const BuiltinArguments& args) {
+    return check_restorecon(std::move(args));
+}
+
+Result<void> check_setprop(const BuiltinArguments& args) {
+    const std::string& name = args[1];
+    if (name.empty()) {
+        return {};
+    }
+    const std::string& value = args[2];
+
+    if (!IsLegalPropertyName(name)) {
+        return Error() << "'" << name << "' is not a legal property name";
+    }
+
+    if (!value.empty()) {
+        if (auto result = IsLegalPropertyValue(name, value); !result) {
+            return result.error();
+        }
+    }
+
+    if (StartsWith(name, "ctl.")) {
+        return Error()
+               << "Do not set ctl. properties from init; call the Service functions directly";
+    }
+
+    static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
+    if (name == kRestoreconProperty) {
+        return Error() << "Do not set '" << kRestoreconProperty
+                       << "' from init; use the restorecon builtin directly";
+    }
+
+    const char* target_context = nullptr;
+    const char* type = nullptr;
+    property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
+
+    if (!CheckType(type, value)) {
+        return Error() << "Property type check failed, value doesn't match expected type '"
+                       << (type ?: "(null)") << "'";
+    }
+
+    return {};
+}
+
+Result<void> check_setrlimit(const BuiltinArguments& args) {
+    ReturnIfAnyArgsEmpty();
+
+    auto rlimit = ParseRlimit(args.args);
+    if (!rlimit) return rlimit.error();
+    return {};
+}
+
+Result<void> check_sysclktz(const BuiltinArguments& args) {
+    ReturnIfAnyArgsEmpty();
+
+    struct timezone tz = {};
+    if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
+        return Error() << "Unable to parse mins_west_of_gmt";
+    }
+    return {};
+}
+
+Result<void> check_wait(const BuiltinArguments& args) {
+    if (args.size() == 3 && !args[2].empty()) {
+        int timeout_int;
+        if (!android::base::ParseInt(args[2], &timeout_int)) {
+            return Error() << "failed to parse timeout";
+        }
+    }
+    return {};
+}
+
+Result<void> check_wait_for_prop(const BuiltinArguments& args) {
+    return check_setprop(std::move(args));
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/check_builtins.h b/init/check_builtins.h
new file mode 100644
index 0000000..fb34556
--- /dev/null
+++ b/init/check_builtins.h
@@ -0,0 +1,44 @@
+/*
+ * 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 "builtin_arguments.h"
+#include "result.h"
+
+namespace android {
+namespace init {
+
+Result<void> check_chown(const BuiltinArguments& args);
+Result<void> check_exec(const BuiltinArguments& args);
+Result<void> check_exec_background(const BuiltinArguments& args);
+Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args);
+Result<void> check_interface_restart(const BuiltinArguments& args);
+Result<void> check_interface_start(const BuiltinArguments& args);
+Result<void> check_interface_stop(const BuiltinArguments& args);
+Result<void> check_load_system_props(const BuiltinArguments& args);
+Result<void> check_loglevel(const BuiltinArguments& args);
+Result<void> check_mkdir(const BuiltinArguments& args);
+Result<void> check_restorecon(const BuiltinArguments& args);
+Result<void> check_restorecon_recursive(const BuiltinArguments& args);
+Result<void> check_setprop(const BuiltinArguments& args);
+Result<void> check_setrlimit(const BuiltinArguments& args);
+Result<void> check_sysclktz(const BuiltinArguments& args);
+Result<void> check_wait(const BuiltinArguments& args);
+Result<void> check_wait_for_prop(const BuiltinArguments& args);
+
+}  // namespace init
+}  // namespace android
diff --git a/init/descriptors.cpp b/init/descriptors.cpp
deleted file mode 100644
index 6265687..0000000
--- a/init/descriptors.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2016 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 "descriptors.h"
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <cutils/android_get_control_file.h>
-#include <cutils/sockets.h>
-
-#include "util.h"
-
-namespace android {
-namespace init {
-
-DescriptorInfo::DescriptorInfo(const std::string& name, const std::string& type, uid_t uid,
-                               gid_t gid, int perm, const std::string& context)
-        : name_(name), type_(type), uid_(uid), gid_(gid), perm_(perm), context_(context) {
-}
-
-DescriptorInfo::~DescriptorInfo() {
-}
-
-std::ostream& operator<<(std::ostream& os, const DescriptorInfo& info) {
-  return os << "  descriptors " << info.name_ << " " << info.type_ << " " << std::oct << info.perm_;
-}
-
-bool DescriptorInfo::operator==(const DescriptorInfo& other) const {
-  return name_ == other.name_ && type_ == other.type_ && key() == other.key();
-}
-
-void DescriptorInfo::CreateAndPublish(const std::string& globalContext) const {
-  // Create
-  const std::string& contextStr = context_.empty() ? globalContext : context_;
-  int fd = Create(contextStr);
-  if (fd < 0) return;
-
-  // Publish
-  std::string publishedName = key() + name_;
-  std::for_each(publishedName.begin(), publishedName.end(),
-                [] (char& c) { c = isalnum(c) ? c : '_'; });
-
-  std::string val = std::to_string(fd);
-  setenv(publishedName.c_str(), val.c_str(), 1);
-
-  // make sure we don't close on exec
-  fcntl(fd, F_SETFD, 0);
-}
-
-void DescriptorInfo::Clean() const {
-}
-
-SocketInfo::SocketInfo(const std::string& name, const std::string& type, uid_t uid,
-                       gid_t gid, int perm, const std::string& context)
-        : DescriptorInfo(name, type, uid, gid, perm, context) {
-}
-
-void SocketInfo::Clean() const {
-    std::string path = android::base::StringPrintf("%s/%s", ANDROID_SOCKET_DIR, name().c_str());
-    unlink(path.c_str());
-}
-
-int SocketInfo::Create(const std::string& context) const {
-    auto types = android::base::Split(type(), "+");
-    int flags =
-        ((types[0] == "stream" ? SOCK_STREAM : (types[0] == "dgram" ? SOCK_DGRAM : SOCK_SEQPACKET)));
-    bool passcred = types.size() > 1 && types[1] == "passcred";
-    return CreateSocket(name().c_str(), flags, passcred, perm(), uid(), gid(), context.c_str());
-}
-
-const std::string SocketInfo::key() const {
-  return ANDROID_SOCKET_ENV_PREFIX;
-}
-
-FileInfo::FileInfo(const std::string& name, const std::string& type, uid_t uid,
-                   gid_t gid, int perm, const std::string& context)
-        // defaults OK for uid,..., they are ignored for this class.
-        : DescriptorInfo(name, type, uid, gid, perm, context) {
-}
-
-int FileInfo::Create(const std::string&) const {
-  int flags = (type() == "r") ? O_RDONLY :
-              (type() == "w") ? O_WRONLY :
-                                O_RDWR;
-
-  // Make sure we do not block on open (eg: devices can chose to block on
-  // carrier detect).  Our intention is never to delay launch of a service
-  // for such a condition.  The service can perform its own blocking on
-  // carrier detect.
-  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(name().c_str(),
-                                                      flags | O_NONBLOCK)));
-
-  if (fd < 0) {
-    PLOG(ERROR) << "Failed to open file '" << name().c_str() << "'";
-    return -1;
-  }
-
-  // Fixup as we set O_NONBLOCK for open, the intent for fd is to block reads.
-  fcntl(fd, F_SETFL, flags);
-
-  LOG(INFO) << "Opened file '" << name().c_str() << "'"
-            << ", flags " << std::oct << flags << std::dec;
-
-  return fd.release();
-}
-
-const std::string FileInfo::key() const {
-  return ANDROID_FILE_ENV_PREFIX;
-}
-
-}  // namespace init
-}  // namespace android
diff --git a/init/descriptors.h b/init/descriptors.h
deleted file mode 100644
index 3bdddfe..0000000
--- a/init/descriptors.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2016 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 _INIT_DESCRIPTORS_H
-#define _INIT_DESCRIPTORS_H
-
-#include <sys/types.h>
-
-#include <string>
-
-namespace android {
-namespace init {
-
-class DescriptorInfo {
- public:
-  DescriptorInfo(const std::string& name, const std::string& type, uid_t uid,
-                 gid_t gid, int perm, const std::string& context);
-  virtual ~DescriptorInfo();
-
-  friend std::ostream& operator<<(std::ostream& os, const class DescriptorInfo& info);
-  bool operator==(const DescriptorInfo& other) const;
-
-  void CreateAndPublish(const std::string& globalContext) const;
-  virtual void Clean() const;
-
- protected:
-  const std::string& name() const { return name_; }
-  const std::string& type() const { return type_; }
-  uid_t uid() const { return uid_; }
-  gid_t gid() const { return gid_; }
-  int perm() const { return perm_; }
-  const std::string& context() const { return context_; }
-
- private:
-  std::string name_;
-  std::string type_;
-  uid_t uid_;
-  gid_t gid_;
-  int perm_;
-  std::string context_;
-
-  virtual int Create(const std::string& globalContext) const = 0;
-  virtual const std::string key() const = 0;
-};
-
-std::ostream& operator<<(std::ostream& os, const DescriptorInfo& info);
-
-class SocketInfo : public DescriptorInfo {
- public:
-  SocketInfo(const std::string& name, const std::string& type, uid_t uid,
-             gid_t gid, int perm, const std::string& context);
-  void Clean() const override;
- private:
-  virtual int Create(const std::string& context) const override;
-  virtual const std::string key() const override;
-};
-
-class FileInfo : public DescriptorInfo {
- public:
-  FileInfo(const std::string& name, const std::string& type, uid_t uid,
-           gid_t gid, int perm, const std::string& context);
- private:
-  virtual int Create(const std::string& context) const override;
-  virtual const std::string key() const override;
-};
-
-}  // namespace init
-}  // namespace android
-
-#endif
diff --git a/init/devices.cpp b/init/devices.cpp
index 159c75e..9fbec64 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -22,7 +22,6 @@
 #include <unistd.h>
 
 #include <chrono>
-#include <map>
 #include <memory>
 #include <string>
 #include <thread>
@@ -36,13 +35,9 @@
 #include <selinux/android.h>
 #include <selinux/selinux.h>
 
-#include "selinux.h"
+#include "selabel.h"
 #include "util.h"
 
-#ifdef _INIT_INIT_H
-#error "Do not include init.h in files used by ueventd; it will expose init's globals"
-#endif
-
 using namespace std::chrono_literals;
 
 using android::base::Basename;
@@ -115,24 +110,16 @@
 // the supplied buffer with the dm module's instantiated name.
 // If it doesn't start with a virtual block device, or there is some
 // error, return false.
-static bool FindDmDevicePartition(const std::string& path, std::string* result) {
-    result->clear();
+static bool FindDmDevice(const std::string& path, std::string* name, std::string* uuid) {
     if (!StartsWith(path, "/devices/virtual/block/dm-")) return false;
-    if (getpid() == 1) return false;  // first_stage_init has no sepolicy needs
 
-    static std::map<std::string, std::string> cache;
-    // wait_for_file will not work, the content is also delayed ...
-    for (android::base::Timer t; t.duration() < 200ms; std::this_thread::sleep_for(10ms)) {
-        if (ReadFileToString("/sys" + path + "/dm/name", result) && !result->empty()) {
-            // Got it, set cache with result, when node arrives
-            cache[path] = *result = Trim(*result);
-            return true;
-        }
+    if (!ReadFileToString("/sys" + path + "/dm/name", name)) {
+        return false;
     }
-    auto it = cache.find(path);
-    if ((it == cache.end()) || (it->second.empty())) return false;
-    // Return cached results, when node goes away
-    *result = it->second;
+    ReadFileToString("/sys" + path + "/dm/uuid", uuid);
+
+    *name = android::base::Trim(*name);
+    *uuid = android::base::Trim(*uuid);
     return true;
 }
 
@@ -329,6 +316,7 @@
     std::string device;
     std::string type;
     std::string partition;
+    std::string uuid;
 
     if (FindPlatformDevice(uevent.path, &device)) {
         // Skip /devices/platform or /devices/ if present
@@ -346,8 +334,12 @@
         type = "pci";
     } else if (FindVbdDevicePrefix(uevent.path, &device)) {
         type = "vbd";
-    } else if (FindDmDevicePartition(uevent.path, &partition)) {
-        return {"/dev/block/mapper/" + partition};
+    } else if (FindDmDevice(uevent.path, &partition, &uuid)) {
+        std::vector<std::string> symlinks = {"/dev/block/mapper/" + partition};
+        if (!uuid.empty()) {
+            symlinks.emplace_back("/dev/block/mapper/by-uuid/" + uuid);
+        }
+        return symlinks;
     } else {
         return {};
     }
@@ -383,10 +375,41 @@
     return links;
 }
 
+static void RemoveDeviceMapperLinks(const std::string& devpath) {
+    std::vector<std::string> dirs = {
+            "/dev/block/mapper",
+            "/dev/block/mapper/by-uuid",
+    };
+    for (const auto& dir : dirs) {
+        if (access(dir.c_str(), F_OK) != 0) continue;
+
+        std::unique_ptr<DIR, decltype(&closedir)> dh(opendir(dir.c_str()), closedir);
+        if (!dh) {
+            PLOG(ERROR) << "Failed to open directory " << dir;
+            continue;
+        }
+
+        struct dirent* dp;
+        std::string link_path;
+        while ((dp = readdir(dh.get())) != nullptr) {
+            if (dp->d_type != DT_LNK) continue;
+
+            auto path = dir + "/" + dp->d_name;
+            if (Readlink(path, &link_path) && link_path == devpath) {
+                unlink(path.c_str());
+            }
+        }
+    }
+}
+
 void DeviceHandler::HandleDevice(const std::string& action, const std::string& devpath, bool block,
                                  int major, int minor, const std::vector<std::string>& links) const {
     if (action == "add") {
         MakeDevice(devpath, block, major, minor, links);
+    }
+
+    // We don't have full device-mapper information until a change event is fired.
+    if (action == "add" || (action == "change" && StartsWith(devpath, "/dev/block/dm-"))) {
         for (const auto& link : links) {
             if (!mkdir_recursive(Dirname(link), 0755)) {
                 PLOG(ERROR) << "Failed to create directory " << Dirname(link);
@@ -405,6 +428,9 @@
     }
 
     if (action == "remove") {
+        if (StartsWith(devpath, "/dev/block/dm-")) {
+            RemoveDeviceMapperLinks(devpath);
+        }
         for (const auto& link : links) {
             std::string link_path;
             if (Readlink(link, &link_path) && link_path == devpath) {
@@ -415,6 +441,23 @@
     }
 }
 
+void DeviceHandler::HandleAshmemUevent(const Uevent& uevent) {
+    if (uevent.device_name == "ashmem") {
+        static const std::string boot_id_path = "/proc/sys/kernel/random/boot_id";
+        std::string boot_id;
+        if (!ReadFileToString(boot_id_path, &boot_id)) {
+            PLOG(ERROR) << "Cannot duplicate ashmem device node. Failed to read " << boot_id_path;
+            return;
+        };
+        boot_id = Trim(boot_id);
+
+        Uevent dup_ashmem_uevent = uevent;
+        dup_ashmem_uevent.device_name += boot_id;
+        dup_ashmem_uevent.path += boot_id;
+        HandleUevent(dup_ashmem_uevent);
+    }
+}
+
 void DeviceHandler::HandleUevent(const Uevent& uevent) {
     if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") {
         FixupSysPermissions(uevent.path, uevent.subsystem);
@@ -459,6 +502,10 @@
     mkdir_recursive(Dirname(devpath), 0755);
 
     HandleDevice(uevent.action, devpath, block, uevent.major, uevent.minor, links);
+
+    // Duplicate /dev/ashmem device and name it /dev/ashmem<boot_id>.
+    // TODO(b/111903542): remove once all users of /dev/ashmem are migrated to libcutils API.
+    HandleAshmemUevent(uevent);
 }
 
 void DeviceHandler::ColdbootDone() {
diff --git a/init/devices.h b/init/devices.h
index 9d39eaa..05d64da 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -84,9 +84,9 @@
     };
 
     Subsystem() {}
-    Subsystem(const std::string& name) : name_(name) {}
-    Subsystem(const std::string& name, DevnameSource source, const std::string& dir_name)
-        : name_(name), devname_source_(source), dir_name_(dir_name) {}
+    Subsystem(std::string name) : name_(std::move(name)) {}
+    Subsystem(std::string name, DevnameSource source, std::string dir_name)
+        : name_(std::move(name)), devname_source_(source), dir_name_(std::move(dir_name)) {}
 
     // Returns the full path for a uevent of a device that is a member of this subsystem,
     // according to the rules parsed from ueventd.rc
@@ -130,6 +130,7 @@
     void HandleDevice(const std::string& action, const std::string& devpath, bool block, int major,
                       int minor, const std::vector<std::string>& links) const;
     void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
+    void HandleAshmemUevent(const Uevent& uevent);
 
     std::vector<Permissions> dev_permissions_;
     std::vector<SysfsPermissions> sysfs_permissions_;
diff --git a/init/devices_test.cpp b/init/devices_test.cpp
index 3e7c1a8..c408bc1 100644
--- a/init/devices_test.cpp
+++ b/init/devices_test.cpp
@@ -30,7 +30,7 @@
 class DeviceHandlerTester {
   public:
     void TestGetSymlinks(const std::string& platform_device, const Uevent& uevent,
-                         const std::vector<std::string> expected_links) {
+                         const std::vector<std::string>& expected_links) {
         TemporaryDir fake_sys_root;
         device_handler_.sysfs_mount_point_ = fake_sys_root.path;
 
diff --git a/init/epoll.cpp b/init/epoll.cpp
index 94dd553..17d63fa 100644
--- a/init/epoll.cpp
+++ b/init/epoll.cpp
@@ -28,17 +28,17 @@
 
 Epoll::Epoll() {}
 
-Result<Success> Epoll::Open() {
-    if (epoll_fd_ >= 0) return Success();
+Result<void> Epoll::Open() {
+    if (epoll_fd_ >= 0) return {};
     epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
 
     if (epoll_fd_ == -1) {
         return ErrnoError() << "epoll_create1 failed";
     }
-    return Success();
+    return {};
 }
 
-Result<Success> Epoll::RegisterHandler(int fd, std::function<void()> handler, uint32_t events) {
+Result<void> Epoll::RegisterHandler(int fd, std::function<void()> handler, uint32_t events) {
     if (!events) {
         return Error() << "Must specify events";
     }
@@ -52,36 +52,41 @@
     // pointer to the std::function in the map directly for epoll_ctl.
     ev.data.ptr = reinterpret_cast<void*>(&it->second);
     if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
-        Result<Success> result = ErrnoError() << "epoll_ctl failed to add fd";
+        Result<void> result = ErrnoError() << "epoll_ctl failed to add fd";
         epoll_handlers_.erase(fd);
         return result;
     }
-    return Success();
+    return {};
 }
 
-Result<Success> Epoll::UnregisterHandler(int fd) {
+Result<void> Epoll::UnregisterHandler(int fd) {
     if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1) {
         return ErrnoError() << "epoll_ctl failed to remove fd";
     }
     if (epoll_handlers_.erase(fd) != 1) {
         return Error() << "Attempting to remove epoll handler for FD without an existing handler";
     }
-    return Success();
+    return {};
 }
 
-Result<Success> Epoll::Wait(std::optional<std::chrono::milliseconds> timeout) {
+Result<std::vector<std::function<void()>*>> Epoll::Wait(
+        std::optional<std::chrono::milliseconds> timeout) {
     int timeout_ms = -1;
     if (timeout && timeout->count() < INT_MAX) {
         timeout_ms = timeout->count();
     }
-    epoll_event ev;
-    auto nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, &ev, 1, timeout_ms));
-    if (nr == -1) {
+    const auto max_events = epoll_handlers_.size();
+    epoll_event ev[max_events];
+    auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, ev, max_events, timeout_ms));
+    if (num_events == -1) {
         return ErrnoError() << "epoll_wait failed";
-    } else if (nr == 1) {
-        std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
     }
-    return Success();
+    std::vector<std::function<void()>*> pending_functions;
+    for (int i = 0; i < num_events; ++i) {
+        pending_functions.emplace_back(reinterpret_cast<std::function<void()>*>(ev[i].data.ptr));
+    }
+
+    return pending_functions;
 }
 
 }  // namespace init
diff --git a/init/epoll.h b/init/epoll.h
index 9789bef..c32a661 100644
--- a/init/epoll.h
+++ b/init/epoll.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_EPOLL_H
-#define _INIT_EPOLL_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/epoll.h>
@@ -24,6 +23,7 @@
 #include <functional>
 #include <map>
 #include <optional>
+#include <vector>
 
 #include <android-base/unique_fd.h>
 
@@ -36,11 +36,11 @@
   public:
     Epoll();
 
-    Result<Success> Open();
-    Result<Success> RegisterHandler(int fd, std::function<void()> handler,
-                                    uint32_t events = EPOLLIN);
-    Result<Success> UnregisterHandler(int fd);
-    Result<Success> Wait(std::optional<std::chrono::milliseconds> timeout);
+    Result<void> Open();
+    Result<void> RegisterHandler(int fd, std::function<void()> handler, uint32_t events = EPOLLIN);
+    Result<void> UnregisterHandler(int fd);
+    Result<std::vector<std::function<void()>*>> Wait(
+            std::optional<std::chrono::milliseconds> timeout);
 
   private:
     android::base::unique_fd epoll_fd_;
@@ -49,5 +49,3 @@
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 740e82c..1dce2d5 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -17,6 +17,10 @@
 #include "firmware_handler.h"
 
 #include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/sendfile.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -26,25 +30,29 @@
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 
+using android::base::ReadFdToString;
+using android::base::Socketpair;
+using android::base::Split;
 using android::base::Timer;
+using android::base::Trim;
 using android::base::unique_fd;
 using android::base::WriteFully;
 
 namespace android {
 namespace init {
 
-static void LoadFirmware(const Uevent& uevent, const std::string& root, int fw_fd, size_t fw_size,
-                         int loading_fd, int data_fd) {
+static void LoadFirmware(const std::string& firmware, const std::string& root, int fw_fd,
+                         size_t fw_size, int loading_fd, int data_fd) {
     // Start transfer.
     WriteFully(loading_fd, "1", 1);
 
     // Copy the firmware.
     int rc = sendfile(data_fd, fw_fd, nullptr, fw_size);
     if (rc == -1) {
-        PLOG(ERROR) << "firmware: sendfile failed { '" << root << "', '" << uevent.firmware
-                    << "' }";
+        PLOG(ERROR) << "firmware: sendfile failed { '" << root << "', '" << firmware << "' }";
     }
 
     // Tell the firmware whether to abort or commit.
@@ -56,39 +64,165 @@
     return access("/dev/.booting", F_OK) == 0;
 }
 
-FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories)
-    : firmware_directories_(std::move(firmware_directories)) {}
+FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories,
+                                 std::vector<ExternalFirmwareHandler> external_firmware_handlers)
+    : firmware_directories_(std::move(firmware_directories)),
+      external_firmware_handlers_(std::move(external_firmware_handlers)) {}
 
-void FirmwareHandler::ProcessFirmwareEvent(const Uevent& uevent) {
-    int booting = IsBooting();
+Result<std::string> FirmwareHandler::RunExternalHandler(const std::string& handler, uid_t uid,
+                                                        const Uevent& uevent) const {
+    unique_fd child_stdout;
+    unique_fd parent_stdout;
+    if (!Socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, &child_stdout, &parent_stdout)) {
+        return ErrnoError() << "Socketpair() for stdout failed";
+    }
 
+    unique_fd child_stderr;
+    unique_fd parent_stderr;
+    if (!Socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, &child_stderr, &parent_stderr)) {
+        return ErrnoError() << "Socketpair() for stderr failed";
+    }
+
+    signal(SIGCHLD, SIG_DFL);
+
+    auto pid = fork();
+    if (pid < 0) {
+        return ErrnoError() << "fork() failed";
+    }
+
+    if (pid == 0) {
+        setenv("FIRMWARE", uevent.firmware.c_str(), 1);
+        setenv("DEVPATH", uevent.path.c_str(), 1);
+        parent_stdout.reset();
+        parent_stderr.reset();
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+        dup2(child_stdout.get(), STDOUT_FILENO);
+        dup2(child_stderr.get(), STDERR_FILENO);
+
+        auto args = Split(handler, " ");
+        std::vector<char*> c_args;
+        for (auto& arg : args) {
+            c_args.emplace_back(arg.data());
+        }
+        c_args.emplace_back(nullptr);
+
+        if (setuid(uid) != 0) {
+            fprintf(stderr, "setuid() failed: %s", strerror(errno));
+            _exit(EXIT_FAILURE);
+        }
+
+        execv(c_args[0], c_args.data());
+        fprintf(stderr, "exec() failed: %s", strerror(errno));
+        _exit(EXIT_FAILURE);
+    }
+
+    child_stdout.reset();
+    child_stderr.reset();
+
+    int status;
+    pid_t waited_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+    if (waited_pid == -1) {
+        return ErrnoError() << "waitpid() failed";
+    }
+
+    std::string stdout_content;
+    if (!ReadFdToString(parent_stdout.get(), &stdout_content)) {
+        return ErrnoError() << "ReadFdToString() for stdout failed";
+    }
+
+    std::string stderr_content;
+    if (ReadFdToString(parent_stderr.get(), &stderr_content)) {
+        auto messages = Split(stderr_content, "\n");
+        for (const auto& message : messages) {
+            if (!message.empty()) {
+                LOG(ERROR) << "External Firmware Handler: " << message;
+            }
+        }
+    } else {
+        LOG(ERROR) << "ReadFdToString() for stderr failed";
+    }
+
+    if (WIFEXITED(status)) {
+        if (WEXITSTATUS(status) == EXIT_SUCCESS) {
+            return Trim(stdout_content);
+        } else {
+            return Error() << "exited with status " << WEXITSTATUS(status);
+        }
+    } else if (WIFSIGNALED(status)) {
+        return Error() << "killed by signal " << WTERMSIG(status);
+    }
+
+    return Error() << "unexpected exit status " << status;
+}
+
+std::string FirmwareHandler::GetFirmwarePath(const Uevent& uevent) const {
+    for (const auto& external_handler : external_firmware_handlers_) {
+        if (external_handler.devpath == uevent.path) {
+            LOG(INFO) << "Launching external firmware handler '" << external_handler.handler_path
+                      << "' for devpath: '" << uevent.path << "' firmware: '" << uevent.firmware
+                      << "'";
+
+            auto result =
+                    RunExternalHandler(external_handler.handler_path, external_handler.uid, uevent);
+            if (!result) {
+                LOG(ERROR) << "Using default firmware; External firmware handler failed: "
+                           << result.error();
+                return uevent.firmware;
+            }
+            if (result->find("..") != std::string::npos) {
+                LOG(ERROR) << "Using default firmware; External firmware handler provided an "
+                              "invalid path, '"
+                           << *result << "'";
+                return uevent.firmware;
+            }
+            LOG(INFO) << "Loading firmware '" << *result << "' in place of '" << uevent.firmware
+                      << "'";
+            return *result;
+        }
+    }
     LOG(INFO) << "firmware: loading '" << uevent.firmware << "' for '" << uevent.path << "'";
+    return uevent.firmware;
+}
 
-    std::string root = "/sys" + uevent.path;
+void FirmwareHandler::ProcessFirmwareEvent(const std::string& root,
+                                           const std::string& firmware) const {
     std::string loading = root + "/loading";
     std::string data = root + "/data";
 
     unique_fd loading_fd(open(loading.c_str(), O_WRONLY | O_CLOEXEC));
     if (loading_fd == -1) {
-        PLOG(ERROR) << "couldn't open firmware loading fd for " << uevent.firmware;
+        PLOG(ERROR) << "couldn't open firmware loading fd for " << firmware;
         return;
     }
 
     unique_fd data_fd(open(data.c_str(), O_WRONLY | O_CLOEXEC));
     if (data_fd == -1) {
-        PLOG(ERROR) << "couldn't open firmware data fd for " << uevent.firmware;
+        PLOG(ERROR) << "couldn't open firmware data fd for " << firmware;
         return;
     }
 
+    std::vector<std::string> attempted_paths_and_errors;
+
+    int booting = IsBooting();
 try_loading_again:
+    attempted_paths_and_errors.clear();
     for (const auto& firmware_directory : firmware_directories_) {
-        std::string file = firmware_directory + uevent.firmware;
+        std::string file = firmware_directory + firmware;
         unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
-        struct stat sb;
-        if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) {
-            LoadFirmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd);
-            return;
+        if (fw_fd == -1) {
+            attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
+                                                    ", open failed: " + strerror(errno));
+            continue;
         }
+        struct stat sb;
+        if (fstat(fw_fd, &sb) == -1) {
+            attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
+                                                    ", fstat failed: " + strerror(errno));
+            continue;
+        }
+        LoadFirmware(firmware, root, fw_fd, sb.st_size, loading_fd, data_fd);
+        return;
     }
 
     if (booting) {
@@ -99,7 +233,10 @@
         goto try_loading_again;
     }
 
-    LOG(ERROR) << "firmware: could not find firmware for " << uevent.firmware;
+    LOG(ERROR) << "firmware: could not find firmware for " << firmware;
+    for (const auto& message : attempted_paths_and_errors) {
+        LOG(ERROR) << message;
+    }
 
     // Write "-1" as our response to the kernel's firmware request, since we have nothing for it.
     write(loading_fd, "-1", 2);
@@ -115,7 +252,8 @@
     }
     if (pid == 0) {
         Timer t;
-        ProcessFirmwareEvent(uevent);
+        auto firmware = GetFirmwarePath(uevent);
+        ProcessFirmwareEvent("/sys" + uevent.path, firmware);
         LOG(INFO) << "loading " << uevent.path << " took " << t;
         _exit(EXIT_SUCCESS);
     }
diff --git a/init/firmware_handler.h b/init/firmware_handler.h
index 3996096..b4138f1 100644
--- a/init/firmware_handler.h
+++ b/init/firmware_handler.h
@@ -14,32 +14,48 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_FIRMWARE_HANDLER_H
-#define _INIT_FIRMWARE_HANDLER_H
+#pragma once
+
+#include <pwd.h>
 
 #include <string>
 #include <vector>
 
+#include "result.h"
 #include "uevent.h"
 #include "uevent_handler.h"
 
 namespace android {
 namespace init {
 
+struct ExternalFirmwareHandler {
+    ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path)
+        : devpath(std::move(devpath)), uid(uid), handler_path(std::move(handler_path)) {}
+    std::string devpath;
+    uid_t uid;
+    std::string handler_path;
+};
+
 class FirmwareHandler : public UeventHandler {
   public:
-    explicit FirmwareHandler(std::vector<std::string> firmware_directories);
+    FirmwareHandler(std::vector<std::string> firmware_directories,
+                    std::vector<ExternalFirmwareHandler> external_firmware_handlers);
     virtual ~FirmwareHandler() = default;
 
     void HandleUevent(const Uevent& uevent) override;
 
   private:
-    void ProcessFirmwareEvent(const Uevent& uevent);
+    friend void FirmwareTestWithExternalHandler(const std::string& test_name,
+                                                bool expect_new_firmware);
+
+    Result<std::string> RunExternalHandler(const std::string& handler, uid_t uid,
+                                           const Uevent& uevent) const;
+    std::string GetFirmwarePath(const Uevent& uevent) const;
+    void ProcessFirmwareEvent(const std::string& root, const std::string& firmware) const;
 
     std::vector<std::string> firmware_directories_;
+    std::vector<ExternalFirmwareHandler> external_firmware_handlers_;
 };
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/firmware_handler_test.cpp b/init/firmware_handler_test.cpp
new file mode 100644
index 0000000..7bb603c
--- /dev/null
+++ b/init/firmware_handler_test.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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 "firmware_handler.h"
+
+#include <stdlib.h>
+#include <iostream>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+
+#include "uevent.h"
+
+using android::base::GetExecutablePath;
+using namespace std::literals;
+
+namespace android {
+namespace init {
+
+void FirmwareTestWithExternalHandler(const std::string& test_name, bool expect_new_firmware) {
+    auto test_path = GetExecutablePath() + " firmware " + test_name;
+    auto external_firmware_handler = ExternalFirmwareHandler(
+            "/devices/led/firmware/test_firmware001.bin", getuid(), test_path);
+
+    auto firmware_handler = FirmwareHandler({"/test"}, {external_firmware_handler});
+
+    auto uevent = Uevent{
+            .path = "/devices/led/firmware/test_firmware001.bin",
+            .firmware = "test_firmware001.bin",
+    };
+
+    if (expect_new_firmware) {
+        EXPECT_EQ("other_firmware001.bin", firmware_handler.GetFirmwarePath(uevent));
+    } else {
+        EXPECT_EQ("test_firmware001.bin", firmware_handler.GetFirmwarePath(uevent));
+    }
+
+    // Always test the base case that the handler isn't invoked if the devpath doesn't match.
+    auto uevent_different_path = Uevent{
+            .path = "/devices/led/not/mine",
+            .firmware = "test_firmware001.bin",
+    };
+    EXPECT_EQ("test_firmware001.bin", firmware_handler.GetFirmwarePath(uevent_different_path));
+}
+
+TEST(firmware_handler, HandleChange) {
+    FirmwareTestWithExternalHandler("HandleChange", true);
+}
+
+int HandleChange(int argc, char** argv) {
+    // Assert that the environment is set up correctly.
+    if (getenv("DEVPATH") != "/devices/led/firmware/test_firmware001.bin"s) {
+        std::cerr << "$DEVPATH not set correctly" << std::endl;
+        return EXIT_FAILURE;
+    }
+    if (getenv("FIRMWARE") != "test_firmware001.bin"s) {
+        std::cerr << "$FIRMWARE not set correctly" << std::endl;
+        return EXIT_FAILURE;
+    }
+    std::cout << "other_firmware001.bin" << std::endl;
+    return 0;
+}
+
+TEST(firmware_handler, HandleAbort) {
+    FirmwareTestWithExternalHandler("HandleAbort", false);
+}
+
+int HandleAbort(int argc, char** argv) {
+    abort();
+    return 0;
+}
+
+TEST(firmware_handler, HandleFailure) {
+    FirmwareTestWithExternalHandler("HandleFailure", false);
+}
+
+int HandleFailure(int argc, char** argv) {
+    std::cerr << "Failed" << std::endl;
+    return EXIT_FAILURE;
+}
+
+TEST(firmware_handler, HandleBadPath) {
+    FirmwareTestWithExternalHandler("HandleBadPath", false);
+}
+
+int HandleBadPath(int argc, char** argv) {
+    std::cout << "../firmware.bin";
+    return 0;
+}
+
+}  // namespace init
+}  // namespace android
+
+// init_test.cpp contains the main entry point for all init tests.
+int FirmwareTestChildMain(int argc, char** argv) {
+    if (argc < 3) {
+        return 1;
+    }
+
+#define RunTest(testname)                           \
+    if (argv[2] == std::string(#testname)) {        \
+        return android::init::testname(argc, argv); \
+    }
+
+    RunTest(HandleChange);
+    RunTest(HandleAbort);
+    RunTest(HandleFailure);
+    RunTest(HandleBadPath);
+
+#undef RunTest
+    return 1;
+}
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 2b89940..bd71cb5 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -24,15 +24,18 @@
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include <filesystem>
 #include <string>
+#include <thread>
 #include <vector>
 
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <modprobe/modprobe.h>
 #include <private/android_filesystem_config.h>
 
 #include "debug_ramdisk.h"
@@ -75,7 +78,7 @@
 
             if (S_ISDIR(info.st_mode)) {
                 is_dir = true;
-                auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+                auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
                 if (fd >= 0) {
                     auto subdir =
                             std::unique_ptr<DIR, decltype(&closedir)>{fdopendir(fd), closedir};
@@ -91,9 +94,50 @@
     }
 }
 
-bool ForceNormalBoot() {
-    std::string cmdline;
-    android::base::ReadFileToString("/proc/cmdline", &cmdline);
+void StartConsole() {
+    if (mknod("/dev/console", S_IFCHR | 0600, makedev(5, 1))) {
+        PLOG(ERROR) << "unable to create /dev/console";
+        return;
+    }
+    pid_t pid = fork();
+    if (pid != 0) {
+        int status;
+        waitpid(pid, &status, 0);
+        LOG(ERROR) << "console shell exited with status " << status;
+        return;
+    }
+    int fd = -1;
+    int tries = 10;
+    // The device driver for console may not be ready yet so retry for a while in case of failure.
+    while (tries--) {
+        fd = open("/dev/console", O_RDWR);
+        if (fd != -1) {
+            break;
+        }
+        std::this_thread::sleep_for(100ms);
+    }
+    if (fd == -1) {
+        LOG(ERROR) << "Could not open /dev/console, errno = " << errno;
+        _exit(127);
+    }
+    ioctl(fd, TIOCSCTTY, 0);
+    dup2(fd, STDIN_FILENO);
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
+    close(fd);
+
+    const char* path = "/system/bin/sh";
+    const char* args[] = {path, nullptr};
+    int rv = execv(path, const_cast<char**>(args));
+    LOG(ERROR) << "unable to execv, returned " << rv << " errno " << errno;
+    _exit(127);
+}
+
+bool FirstStageConsole(const std::string& cmdline) {
+    return cmdline.find("androidboot.first_stage_console=1") != std::string::npos;
+}
+
+bool ForceNormalBoot(const std::string& cmdline) {
     return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
 }
 
@@ -108,7 +152,7 @@
 
     std::vector<std::pair<std::string, int>> errors;
 #define CHECKCALL(x) \
-    if (x != 0) errors.emplace_back(#x " failed", errno);
+    if ((x) != 0) errors.emplace_back(#x " failed", errno);
 
     // Clear the umask.
     umask(0);
@@ -126,6 +170,8 @@
 #undef MAKE_STR
     // Don't expose the raw commandline to unprivileged processes.
     CHECKCALL(chmod("/proc/cmdline", 0440));
+    std::string cmdline;
+    android::base::ReadFileToString("/proc/cmdline", &cmdline);
     gid_t groups[] = {AID_READPROC};
     CHECKCALL(setgroups(arraysize(groups), groups));
     CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
@@ -158,10 +204,6 @@
     // part of the product partition, e.g. because they are mounted read-write.
     CHECKCALL(mkdir("/mnt/product", 0755));
 
-    // /apex is used to mount APEXes
-    CHECKCALL(mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
-                    "mode=0755,uid=0,gid=0"));
-
     // /debug_ramdisk is used to preserve additional files from the debug ramdisk
     CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
                     "mode=0755,uid=0,gid=0"));
@@ -192,7 +234,21 @@
         old_root_dir.reset();
     }
 
-    if (ForceNormalBoot()) {
+    Modprobe m({"/lib/modules"});
+    auto want_console = ALLOW_FIRST_STAGE_CONSOLE && FirstStageConsole(cmdline);
+    if (!m.LoadListedModules(!want_console)) {
+        if (want_console) {
+            LOG(ERROR) << "Failed to load kernel modules, starting console";
+        } else {
+            LOG(FATAL) << "Failed to load kernel modules";
+        }
+    }
+
+    if (want_console) {
+        StartConsole();
+    }
+
+    if (ForceNormalBoot(cmdline)) {
         mkdir("/first_stage_ramdisk", 0755);
         // SwitchRoot() must be called with a mount point as the target, so we bind mount the
         // target directory to itself here.
@@ -231,12 +287,15 @@
 
     SetInitAvbVersionInRecovery();
 
-    static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
-    uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
-    setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
+    setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(),
+           1);
 
     const char* path = "/system/bin/init";
     const char* args[] = {path, "selinux_setup", nullptr};
+    auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
+    close(fd);
     execv(path, const_cast<char**>(args));
 
     // execv() only returns if an error happened, in which case we
diff --git a/init/first_stage_init.h b/init/first_stage_init.h
index 0476e44..7de816f 100644
--- a/init/first_stage_init.h
+++ b/init/first_stage_init.h
@@ -21,5 +21,7 @@
 
 int FirstStageMain(int argc, char** argv);
 
+static constexpr char kEnvFirstStageStartedAt[] = "FIRST_STAGE_STARTED_AT";
+
 }  // namespace init
 }  // namespace android
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 3e76556..e5e99e1 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -34,8 +34,10 @@
 #include <fs_mgr.h>
 #include <fs_mgr_dm_linear.h>
 #include <fs_mgr_overlayfs.h>
+#include <libfiemap/image_manager.h>
 #include <libgsi/libgsi.h>
 #include <liblp/liblp.h>
+#include <libsnapshot/snapshot.h>
 
 #include "devices.h"
 #include "switch_root.h"
@@ -45,16 +47,19 @@
 
 using android::base::Split;
 using android::base::Timer;
+using android::fiemap::IImageManager;
 using android::fs_mgr::AvbHandle;
 using android::fs_mgr::AvbHandleStatus;
 using android::fs_mgr::AvbHashtreeResult;
 using android::fs_mgr::AvbUniquePtr;
-using android::fs_mgr::BuildGsiSystemFstabEntry;
 using android::fs_mgr::Fstab;
 using android::fs_mgr::FstabEntry;
 using android::fs_mgr::ReadDefaultFstab;
 using android::fs_mgr::ReadFstabFromDt;
 using android::fs_mgr::SkipMountingPartitions;
+using android::fs_mgr::TransformFstabForDsu;
+using android::init::WriteFile;
+using android::snapshot::SnapshotManager;
 
 using namespace std::literals;
 
@@ -75,8 +80,9 @@
     bool InitDevices();
 
   protected:
-    ListenerAction HandleBlockDevice(const std::string& name, const Uevent&);
-    bool InitRequiredDevices();
+    ListenerAction HandleBlockDevice(const std::string& name, const Uevent&,
+                                     std::set<std::string>* required_devices);
+    bool InitRequiredDevices(std::set<std::string> devices);
     bool InitMappedDevice(const std::string& verity_device);
     bool InitDeviceMapper();
     bool CreateLogicalPartitions();
@@ -87,22 +93,21 @@
     bool TrySwitchSystemAsRoot();
     bool TrySkipMountingPartitions();
     bool IsDmLinearEnabled();
-    bool GetDmLinearMetadataDevice();
+    void GetDmLinearMetadataDevice(std::set<std::string>* devices);
     bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
-    void UseGsiIfPresent();
+    void UseDsuIfPresent();
 
-    ListenerAction UeventCallback(const Uevent& uevent);
+    ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices);
 
     // Pure virtual functions.
-    virtual bool GetDmVerityDevices() = 0;
+    virtual bool GetDmVerityDevices(std::set<std::string>* devices) = 0;
     virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
 
     bool need_dm_verity_;
-    bool gsi_not_on_userdata_ = false;
+    bool dsu_not_on_userdata_ = false;
 
     Fstab fstab_;
     std::string lp_metadata_partition_;
-    std::set<std::string> required_devices_partition_names_;
     std::string super_partition_name_;
     std::unique_ptr<DeviceHandler> device_handler_;
     UeventListener uevent_listener_;
@@ -114,7 +119,7 @@
     ~FirstStageMountVBootV1() override = default;
 
   protected:
-    bool GetDmVerityDevices() override;
+    bool GetDmVerityDevices(std::set<std::string>* devices) override;
     bool SetUpDmVerity(FstabEntry* fstab_entry) override;
 };
 
@@ -126,7 +131,7 @@
     ~FirstStageMountVBootV2() override = default;
 
   protected:
-    bool GetDmVerityDevices() override;
+    bool GetDmVerityDevices(std::set<std::string>* devices) override;
     bool SetUpDmVerity(FstabEntry* fstab_entry) override;
     bool InitAvbHandle();
 
@@ -244,15 +249,19 @@
 
     if (!InitDevices()) return false;
 
-    if (!CreateLogicalPartitions()) return false;
-
     if (!MountPartitions()) return false;
 
     return true;
 }
 
 bool FirstStageMount::InitDevices() {
-    return GetDmLinearMetadataDevice() && GetDmVerityDevices() && InitRequiredDevices();
+    std::set<std::string> devices;
+    GetDmLinearMetadataDevice(&devices);
+
+    if (!GetDmVerityDevices(&devices)) {
+        return false;
+    }
+    return InitRequiredDevices(std::move(devices));
 }
 
 bool FirstStageMount::IsDmLinearEnabled() {
@@ -262,47 +271,46 @@
     return false;
 }
 
-bool FirstStageMount::GetDmLinearMetadataDevice() {
+void FirstStageMount::GetDmLinearMetadataDevice(std::set<std::string>* devices) {
     // Add any additional devices required for dm-linear mappings.
     if (!IsDmLinearEnabled()) {
-        return true;
+        return;
     }
 
-    required_devices_partition_names_.emplace(super_partition_name_);
-    return true;
+    devices->emplace(super_partition_name_);
 }
 
-// Creates devices with uevent->partition_name matching one in the member variable
-// required_devices_partition_names_. Found partitions will then be removed from it
-// for the subsequent member function to check which devices are NOT created.
-bool FirstStageMount::InitRequiredDevices() {
-    if (required_devices_partition_names_.empty()) {
+// Creates devices with uevent->partition_name matching ones in the given set.
+// Found partitions will then be removed from it for the subsequent member
+// function to check which devices are NOT created.
+bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
+    if (!InitDeviceMapper()) {
+        return false;
+    }
+
+    if (devices.empty()) {
         return true;
     }
 
-    if (IsDmLinearEnabled() || need_dm_verity_) {
-        if (!InitDeviceMapper()) {
-            return false;
-        }
-    }
-
-    auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); };
+    auto uevent_callback = [&, this](const Uevent& uevent) {
+        return UeventCallback(uevent, &devices);
+    };
     uevent_listener_.RegenerateUevents(uevent_callback);
 
-    // UeventCallback() will remove found partitions from required_devices_partition_names_.
-    // So if it isn't empty here, it means some partitions are not found.
-    if (!required_devices_partition_names_.empty()) {
+    // UeventCallback() will remove found partitions from |devices|. So if it
+    // isn't empty here, it means some partitions are not found.
+    if (!devices.empty()) {
         LOG(INFO) << __PRETTY_FUNCTION__
                   << ": partition(s) not found in /sys, waiting for their uevent(s): "
-                  << android::base::Join(required_devices_partition_names_, ", ");
+                  << android::base::Join(devices, ", ");
         Timer t;
         uevent_listener_.Poll(uevent_callback, 10s);
         LOG(INFO) << "Wait for partitions returned after " << t;
     }
 
-    if (!required_devices_partition_names_.empty()) {
+    if (!devices.empty()) {
         LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: "
-                   << android::base::Join(required_devices_partition_names_, ", ");
+                   << android::base::Join(devices, ", ");
         return false;
     }
 
@@ -335,27 +343,20 @@
 }
 
 bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
+    std::set<std::string> devices;
+
     auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
     for (const auto& partition_name : partition_names) {
         // The super partition was found in the earlier pass.
         if (partition_name == super_partition_name_) {
             continue;
         }
-        required_devices_partition_names_.emplace(partition_name);
+        devices.emplace(partition_name);
     }
-    if (required_devices_partition_names_.empty()) {
+    if (devices.empty()) {
         return true;
     }
-
-    auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); };
-    uevent_listener_.RegenerateUevents(uevent_callback);
-
-    if (!required_devices_partition_names_.empty()) {
-        LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: "
-                   << android::base::Join(required_devices_partition_names_, ", ");
-        return false;
-    }
-    return true;
+    return InitRequiredDevices(std::move(devices));
 }
 
 bool FirstStageMount::CreateLogicalPartitions() {
@@ -368,6 +369,21 @@
         return false;
     }
 
+    if (SnapshotManager::IsSnapshotManagerNeeded()) {
+        auto sm = SnapshotManager::NewForFirstStageMount();
+        if (!sm) {
+            return false;
+        }
+        if (sm->NeedSnapshotsInFirstStageMount()) {
+            // When COW images are present for snapshots, they are stored on
+            // the data partition.
+            if (!InitRequiredDevices({"userdata"})) {
+                return false;
+            }
+            return sm->CreateLogicalAndSnapshotPartitions(lp_metadata_partition_);
+        }
+    }
+
     auto metadata = android::fs_mgr::ReadCurrentMetadata(lp_metadata_partition_);
     if (!metadata) {
         LOG(ERROR) << "Could not read logical partition metadata from " << lp_metadata_partition_;
@@ -379,20 +395,21 @@
     return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), lp_metadata_partition_);
 }
 
-ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent) {
+ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent,
+                                                  std::set<std::string>* required_devices) {
     // Matches partition name to create device nodes.
     // Both required_devices_partition_names_ and uevent->partition_name have A/B
     // suffix when A/B is used.
-    auto iter = required_devices_partition_names_.find(name);
-    if (iter != required_devices_partition_names_.end()) {
+    auto iter = required_devices->find(name);
+    if (iter != required_devices->end()) {
         LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
         if (IsDmLinearEnabled() && name == super_partition_name_) {
             std::vector<std::string> links = device_handler_->GetBlockDeviceSymlinks(uevent);
             lp_metadata_partition_ = links[0];
         }
-        required_devices_partition_names_.erase(iter);
+        required_devices->erase(iter);
         device_handler_->HandleUevent(uevent);
-        if (required_devices_partition_names_.empty()) {
+        if (required_devices->empty()) {
             return ListenerAction::kStop;
         } else {
             return ListenerAction::kContinue;
@@ -401,18 +418,19 @@
     return ListenerAction::kContinue;
 }
 
-ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) {
+ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent,
+                                               std::set<std::string>* required_devices) {
     // Ignores everything that is not a block device.
     if (uevent.subsystem != "block") {
         return ListenerAction::kContinue;
     }
 
     if (!uevent.partition_name.empty()) {
-        return HandleBlockDevice(uevent.partition_name, uevent);
+        return HandleBlockDevice(uevent.partition_name, uevent, required_devices);
     } else {
         size_t base_idx = uevent.path.rfind('/');
         if (base_idx != std::string::npos) {
-            return HandleBlockDevice(uevent.path.substr(base_idx + 1), uevent);
+            return HandleBlockDevice(uevent.path.substr(base_idx + 1), uevent, required_devices);
         }
     }
     // Not found a partition or find an unneeded partition, continue to find others.
@@ -495,14 +513,7 @@
 // this case, we mount system first then pivot to it.  From that point on,
 // we are effectively identical to a system-as-root device.
 bool FirstStageMount::TrySwitchSystemAsRoot() {
-    auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
-        return entry.mount_point == "/metadata";
-    });
-    if (metadata_partition != fstab_.end()) {
-        if (MountPartition(metadata_partition, true /* erase_same_mounts */)) {
-            UseGsiIfPresent();
-        }
-    }
+    UseDsuIfPresent();
 
     auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
         return entry.mount_point == "/system";
@@ -511,7 +522,7 @@
     if (system_partition == fstab_.end()) return true;
 
     if (MountPartition(system_partition, false /* erase_same_mounts */)) {
-        if (gsi_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
+        if (dsu_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
             LOG(ERROR) << "check_most_at_once forbidden on external media";
             return false;
         }
@@ -525,6 +536,17 @@
 }
 
 bool FirstStageMount::MountPartitions() {
+    // Mount /metadata before creating logical partitions, since we need to
+    // know whether a snapshot merge is in progress.
+    auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
+        return entry.mount_point == "/metadata";
+    });
+    if (metadata_partition != fstab_.end()) {
+        MountPartition(metadata_partition, true /* erase_same_mounts */);
+    }
+
+    if (!CreateLogicalPartitions()) return false;
+
     if (!TrySwitchSystemAsRoot()) return false;
 
     if (!SkipMountingPartitions(&fstab_)) return false;
@@ -565,17 +587,7 @@
     const auto devices = fs_mgr_overlayfs_required_devices(&fstab_);
     for (auto const& device : devices) {
         if (android::base::StartsWith(device, "/dev/block/by-name/")) {
-            required_devices_partition_names_.emplace(basename(device.c_str()));
-            auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); };
-            uevent_listener_.RegenerateUevents(uevent_callback);
-            if (!required_devices_partition_names_.empty()) {
-                uevent_listener_.Poll(uevent_callback, 10s);
-                if (!required_devices_partition_names_.empty()) {
-                    LOG(ERROR) << __PRETTY_FUNCTION__
-                               << ": partition(s) not found after polling timeout: "
-                               << android::base::Join(required_devices_partition_names_, ", ");
-                }
-            }
+            InitRequiredDevices({basename(device.c_str())});
         } else {
             InitMappedDevice(device);
         }
@@ -586,65 +598,43 @@
     return true;
 }
 
-void FirstStageMount::UseGsiIfPresent() {
-    std::string metadata_file, error;
+void FirstStageMount::UseDsuIfPresent() {
+    std::string error;
 
-    if (!android::gsi::CanBootIntoGsi(&metadata_file, &error)) {
-        LOG(INFO) << "GSI " << error << ", proceeding with normal boot";
+    if (!android::gsi::CanBootIntoGsi(&error)) {
+        LOG(INFO) << "DSU " << error << ", proceeding with normal boot";
         return;
     }
 
-    auto metadata = android::fs_mgr::ReadFromImageFile(metadata_file.c_str());
-    if (!metadata) {
-        LOG(ERROR) << "GSI partition layout could not be read";
-        return;
-    }
-
-    if (!InitDmLinearBackingDevices(*metadata.get())) {
-        return;
-    }
-
-    // Device-mapper might not be ready if the device doesn't use DAP or verity
-    // (for example, hikey).
-    if (access("/dev/device-mapper", F_OK) && !InitDeviceMapper()) {
-        return;
-    }
-
-    // Find the name of the super partition for the GSI. It will either be
-    // "userdata", or a block device such as an sdcard. There are no by-name
-    // partitions other than userdata that we support installing GSIs to.
-    auto super = GetMetadataSuperBlockDevice(*metadata.get());
-    std::string super_name = android::fs_mgr::GetBlockDevicePartitionName(*super);
-    std::string super_path;
-    if (super_name == "userdata") {
-        super_path = "/dev/block/by-name/" + super_name;
-    } else {
-        super_path = "/dev/block/" + super_name;
-    }
-
-    if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path)) {
-        LOG(ERROR) << "GSI partition layout could not be instantiated";
+    auto init_devices = [this](std::set<std::string> devices) -> bool {
+        if (devices.count("userdata") == 0 || devices.size() > 1) {
+            dsu_not_on_userdata_ = true;
+        }
+        return InitRequiredDevices(std::move(devices));
+    };
+    auto images = IImageManager::Open("dsu", 0ms);
+    if (!images || !images->MapAllImages(init_devices)) {
+        LOG(ERROR) << "DSU partition layout could not be instantiated";
         return;
     }
 
     if (!android::gsi::MarkSystemAsGsi()) {
-        PLOG(ERROR) << "GSI indicator file could not be written";
+        PLOG(ERROR) << "DSU indicator file could not be written";
         return;
     }
 
-    // Replace the existing system fstab entry.
-    auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
-        return entry.mount_point == "/system";
-    });
-    if (system_partition != fstab_.end()) {
-        fstab_.erase(system_partition);
+    std::string lp_names = "";
+    std::vector<std::string> dsu_partitions;
+    for (auto&& name : images->GetAllBackingImages()) {
+        dsu_partitions.push_back(name);
+        lp_names += name + ",";
     }
-    fstab_.emplace_back(BuildGsiSystemFstabEntry());
-    gsi_not_on_userdata_ = (super_name != "userdata");
+    // Publish the logical partition names for TransformFstabForDsu
+    WriteFile(gsi::kGsiLpNamesFile, lp_names);
+    TransformFstabForDsu(&fstab_, dsu_partitions);
 }
 
-bool FirstStageMountVBootV1::GetDmVerityDevices() {
-    std::string verity_loc_device;
+bool FirstStageMountVBootV1::GetDmVerityDevices(std::set<std::string>* devices) {
     need_dm_verity_ = false;
 
     for (const auto& fstab_entry : fstab_) {
@@ -657,32 +647,16 @@
         if (fstab_entry.fs_mgr_flags.verify) {
             need_dm_verity_ = true;
         }
-        // Checks if verity metadata is on a separate partition. Note that it is
-        // not partition specific, so there must be only one additional partition
-        // that carries verity state.
-        if (!fstab_entry.verity_loc.empty()) {
-            if (verity_loc_device.empty()) {
-                verity_loc_device = fstab_entry.verity_loc;
-            } else if (verity_loc_device != fstab_entry.verity_loc) {
-                LOG(ERROR) << "More than one verity_loc found: " << verity_loc_device << ", "
-                           << fstab_entry.verity_loc;
-                return false;
-            }
-        }
     }
 
-    // Includes the partition names of fstab records and verity_loc_device (if any).
+    // Includes the partition names of fstab records.
     // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
     for (const auto& fstab_entry : fstab_) {
         if (!fstab_entry.fs_mgr_flags.logical) {
-            required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str()));
+            devices->emplace(basename(fstab_entry.blk_device.c_str()));
         }
     }
 
-    if (!verity_loc_device.empty()) {
-        required_devices_partition_names_.emplace(basename(verity_loc_device.c_str()));
-    }
-
     return true;
 }
 
@@ -730,7 +704,7 @@
     }
 }
 
-bool FirstStageMountVBootV2::GetDmVerityDevices() {
+bool FirstStageMountVBootV2::GetDmVerityDevices(std::set<std::string>* devices) {
     need_dm_verity_ = false;
 
     std::set<std::string> logical_partitions;
@@ -744,7 +718,7 @@
             // Don't try to find logical partitions via uevent regeneration.
             logical_partitions.emplace(basename(fstab_entry.blk_device.c_str()));
         } else {
-            required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str()));
+            devices->emplace(basename(fstab_entry.blk_device.c_str()));
         }
     }
 
@@ -761,11 +735,11 @@
             if (logical_partitions.count(partition_name)) {
                 continue;
             }
-            // required_devices_partition_names_ is of type std::set so it's not an issue
-            // to emplace a partition twice. e.g., /vendor might be in both places:
+            // devices is of type std::set so it's not an issue to emplace a
+            // partition twice. e.g., /vendor might be in both places:
             //   - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
             //   - mount_fstab_recs_: /vendor_a
-            required_devices_partition_names_.emplace(partition_name);
+            devices->emplace(partition_name);
         }
     }
     return true;
diff --git a/init/fscrypt_init_extensions.cpp b/init/fscrypt_init_extensions.cpp
new file mode 100644
index 0000000..fbd8189
--- /dev/null
+++ b/init/fscrypt_init_extensions.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 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 "fscrypt_init_extensions.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fts.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#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 <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <fscrypt/fscrypt.h>
+#include <keyutils.h>
+#include <logwrap/logwrap.h>
+
+#define TAG "fscrypt"
+
+using namespace android::fscrypt;
+
+bool FscryptInstallKeyring() {
+    if (keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0) != -1) {
+        LOG(INFO) << "Keyring is already created";
+        return true;
+    }
+    key_serial_t device_keyring = add_key("keyring", "fscrypt", 0, 0, KEY_SPEC_SESSION_KEYRING);
+
+    if (device_keyring == -1) {
+        PLOG(ERROR) << "Failed to create keyring";
+        return false;
+    }
+    LOG(INFO) << "Keyring created with id " << device_keyring << " in process " << getpid();
+    return true;
+}
+
+// TODO(b/139378601): use a single central implementation of this.
+static void delete_dir_contents(const std::string& dir) {
+    char* const paths[2] = {const_cast<char*>(dir.c_str()), nullptr};
+    FTS* fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr);
+    FTSENT* cur;
+    while ((cur = fts_read(fts)) != nullptr) {
+        if (cur->fts_info == FTS_ERR) {
+            PLOG(ERROR) << "fts_read";
+            break;
+        }
+        if (dir == cur->fts_path) {
+            continue;
+        }
+        switch (cur->fts_info) {
+            case FTS_D:
+                break;  // Ignore these
+            case FTS_DP:
+                if (rmdir(cur->fts_path) == -1) {
+                    PLOG(ERROR) << "rmdir " << cur->fts_path;
+                }
+                break;
+            default:
+                PLOG(ERROR) << "FTS unexpected type " << cur->fts_info << " at " << cur->fts_path;
+                if (rmdir(cur->fts_path) != -1) break;
+                // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
+                FALLTHROUGH_INTENDED;
+            case FTS_F:
+            case FTS_SL:
+            case FTS_SLNONE:
+                if (unlink(cur->fts_path) == -1) {
+                    PLOG(ERROR) << "unlink " << cur->fts_path;
+                }
+                break;
+        }
+    }
+
+    if (fts_close(fts) != 0) {
+        PLOG(ERROR) << "fts_close";
+    }
+}
+
+// Look up an encryption policy  The policy (key reference
+// and encryption options) to use is read from files that were written by vold.
+static bool LookupPolicy(const std::string& ref_basename, EncryptionPolicy* policy) {
+    std::string ref_filename = std::string("/data") + ref_basename;
+    if (!android::base::ReadFileToString(ref_filename, &policy->key_raw_ref)) {
+        LOG(ERROR) << "Unable to read system policy with name " << ref_filename;
+        return false;
+    }
+
+    auto options_filename = std::string("/data") + fscrypt_key_mode;
+    std::string options_string;
+    if (!android::base::ReadFileToString(options_filename, &options_string)) {
+        LOG(ERROR) << "Cannot read encryption options string";
+        return false;
+    }
+    if (!ParseOptions(options_string, &policy->options)) {
+        LOG(ERROR) << "Invalid encryption options string: " << options_string;
+        return false;
+    }
+    return true;
+}
+
+static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) {
+    if (!EnsurePolicy(policy, dir)) {
+        std::string ref_hex;
+        BytesToHex(policy.key_raw_ref, &ref_hex);
+        LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!";
+        return false;
+    }
+    return true;
+}
+
+static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) {
+    EncryptionPolicy policy;
+    if (!LookupPolicy(ref_basename, &policy)) return false;
+    if (!EnsurePolicyOrLog(policy, dir)) return false;
+    return true;
+}
+
+bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
+                               const std::string& dir) {
+    if (action == FscryptAction::kNone) {
+        return true;
+    }
+    if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
+        return true;
+    }
+    if (action == FscryptAction::kDeleteIfNecessary) {
+        LOG(ERROR) << "Setting policy failed, deleting: " << dir;
+        delete_dir_contents(dir);
+        return SetPolicyOn(ref_basename, dir);
+    }
+    return false;
+}
diff --git a/libmemunreachable/tests/HostMallocStub.cpp b/init/fscrypt_init_extensions.h
similarity index 67%
copy from libmemunreachable/tests/HostMallocStub.cpp
copy to init/fscrypt_init_extensions.h
index 0ef0487..d357bb2 100644
--- a/libmemunreachable/tests/HostMallocStub.cpp
+++ b/init/fscrypt_init_extensions.h
@@ -14,8 +14,17 @@
  * limitations under the License.
  */
 
-#include "bionic.h"
+#pragma once
 
-void malloc_disable() {}
+#include <string>
 
-void malloc_enable() {}
+enum class FscryptAction {
+    kNone,
+    kAttempt,
+    kRequire,
+    kDeleteIfNecessary,
+};
+
+bool FscryptInstallKeyring();
+bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
+                               const std::string& dir);
diff --git a/init/host_builtin_map.py b/init/host_builtin_map.py
new file mode 100755
index 0000000..6afcb17
--- /dev/null
+++ b/init/host_builtin_map.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+"""Generates the builtins map to be used by host_init_verifier.
+
+It copies the builtin function map from builtins.cpp, then replaces do_xxx() functions with the
+equivalent check_xxx() if found in check_builtins.cpp.
+
+"""
+
+import re
+import argparse
+
+parser = argparse.ArgumentParser('host_builtin_map.py')
+parser.add_argument('--builtins', required=True, help='Path to builtins.cpp')
+parser.add_argument('--check_builtins', required=True, help='Path to check_builtins.cpp')
+args = parser.parse_args()
+
+CHECK_REGEX = re.compile(r'.+check_(\S+)\(.+')
+check_functions = []
+with open(args.check_builtins) as check_file:
+  for line in check_file:
+    match = CHECK_REGEX.match(line)
+    if match:
+      check_functions.append(match.group(1))
+
+function_map = []
+with open(args.builtins) as builtins_file:
+  in_function_map = False
+  for line in builtins_file:
+    if '// Builtin-function-map start' in line:
+      in_function_map = True
+    elif '// Builtin-function-map end' in line:
+      in_function_map = False
+    elif in_function_map:
+      function_map.append(line)
+
+DO_REGEX = re.compile(r'.+do_([^\}]+).+')
+FUNCTION_REGEX = re.compile(r'(do_[^\}]+)')
+for line in function_map:
+  match = DO_REGEX.match(line)
+  if match:
+    if match.group(1) in check_functions:
+      print line.replace('do_', 'check_'),
+    else:
+      print FUNCTION_REGEX.sub('check_stub', line),
+  else:
+    print line,
diff --git a/init/host_import_parser.cpp b/init/host_import_parser.cpp
index 93e363f..aa80199 100644
--- a/init/host_import_parser.cpp
+++ b/init/host_import_parser.cpp
@@ -23,16 +23,16 @@
 namespace android {
 namespace init {
 
-Result<Success> HostImportParser::ParseSection(std::vector<std::string>&& args, const std::string&,
-                                               int) {
+Result<void> HostImportParser::ParseSection(std::vector<std::string>&& args, const std::string&,
+                                            int) {
     if (args.size() != 2) {
         return Error() << "single argument needed for import\n";
     }
 
-    return Success();
+    return {};
 }
 
-Result<Success> HostImportParser::ParseLineSection(std::vector<std::string>&&, int) {
+Result<void> HostImportParser::ParseLineSection(std::vector<std::string>&&, int) {
     return Error() << "Unexpected line found after import statement";
 }
 
diff --git a/init/host_import_parser.h b/init/host_import_parser.h
index 52b8891..d6f7286 100644
--- a/init/host_import_parser.h
+++ b/init/host_import_parser.h
@@ -27,8 +27,8 @@
 class HostImportParser : public SectionParser {
   public:
     HostImportParser() {}
-    Result<Success> ParseSection(std::vector<std::string>&& args, const std::string&, int) override;
-    Result<Success> ParseLineSection(std::vector<std::string>&&, int) override;
+    Result<void> ParseSection(std::vector<std::string>&& args, const std::string&, int) override;
+    Result<void> ParseLineSection(std::vector<std::string>&&, int) override;
 };
 
 }  // namespace init
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
deleted file mode 100644
index b85e54a..0000000
--- a/init/host_init_stubs.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#include "host_init_stubs.h"
-
-#include <android-base/properties.h>
-
-// unistd.h
-int setgroups(size_t __size, const gid_t* __list) {
-    return 0;
-}
-
-namespace android {
-namespace init {
-
-// init.h
-std::string default_console = "/dev/console";
-
-// property_service.h
-bool CanReadProperty(const std::string& source_context, const std::string& name) {
-    return true;
-}
-uint32_t SetProperty(const std::string& key, const std::string& value) {
-    android::base::SetProperty(key, value);
-    return 0;
-}
-uint32_t (*property_set)(const std::string& name, const std::string& value) = SetProperty;
-uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&, const ucred&,
-                           std::string*) {
-    return 0;
-}
-
-// selinux.h
-int SelinuxGetVendorAndroidVersion() {
-    return 10000;
-}
-void SelabelInitialize() {}
-
-bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
-    return false;
-}
-
-}  // namespace init
-}  // namespace android
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index f6e9676..caa8f8d 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_HOST_INIT_STUBS_H
-#define _INIT_HOST_INIT_STUBS_H
+#pragma once
 
 #include <stddef.h>
 #include <sys/socket.h>
@@ -23,39 +22,40 @@
 
 #include <string>
 
+#include <android-base/properties.h>
+
 // android/api-level.h
 #define __ANDROID_API_P__ 28
+#define __ANDROID_API_Q__ 29
+#define __ANDROID_API_R__ 30
 
 // sys/system_properties.h
 #define PROP_VALUE_MAX 92
 
-// unistd.h
-int setgroups(size_t __size, const gid_t* __list);
-
 namespace android {
 namespace init {
 
-// init.h
-extern std::string default_console;
-
 // property_service.h
-bool CanReadProperty(const std::string& source_context, const std::string& name);
-extern uint32_t (*property_set)(const std::string& name, const std::string& value);
-uint32_t HandlePropertySet(const std::string& name, const std::string& value,
-                           const std::string& source_context, const ucred& cr, std::string* error);
+inline bool CanReadProperty(const std::string&, const std::string&) {
+    return true;
+}
 
 // reboot_utils.h
 inline void SetFatalRebootTarget() {}
-inline void __attribute__((noreturn)) InitFatalReboot() {
+inline void __attribute__((noreturn)) InitFatalReboot(int signal_number) {
     abort();
 }
 
+// selabel.h
+inline void SelabelInitialize() {}
+inline bool SelabelLookupFileContext(const std::string&, int, std::string*) {
+    return false;
+}
+
 // selinux.h
-int SelinuxGetVendorAndroidVersion();
-void SelabelInitialize();
-bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
+inline int SelinuxGetVendorAndroidVersion() {
+    return 10000;
+}
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/host_init_verifier.cpp b/init/host_init_verifier.cpp
index 8407729..22de846 100644
--- a/init/host_init_verifier.cpp
+++ b/init/host_init_verifier.cpp
@@ -14,12 +14,17 @@
 // limitations under the License.
 //
 
+#include "host_init_verifier.h"
+
 #include <errno.h>
+#include <getopt.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <fstream>
 #include <iostream>
+#include <iterator>
 #include <string>
 #include <vector>
 
@@ -27,15 +32,21 @@
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
+#include <hidl/metadata.h>
+#include <property_info_serializer/property_info_serializer.h>
 
 #include "action.h"
 #include "action_manager.h"
 #include "action_parser.h"
+#include "check_builtins.h"
 #include "host_import_parser.h"
 #include "host_init_stubs.h"
+#include "interface_utils.h"
 #include "parser.h"
 #include "result.h"
 #include "service.h"
+#include "service_list.h"
+#include "service_parser.h"
 
 #define EXCLUDE_FS_CONFIG_STRUCTURES
 #include "generated_android_ids.h"
@@ -45,10 +56,14 @@
 using android::base::ParseInt;
 using android::base::ReadFileToString;
 using android::base::Split;
+using android::properties::BuildTrie;
+using android::properties::ParsePropertyInfoFile;
+using android::properties::PropertyInfoArea;
+using android::properties::PropertyInfoEntry;
 
-static std::string passwd_file;
+static std::vector<std::string> passwd_files;
 
-static std::vector<std::pair<std::string, int>> GetVendorPasswd() {
+static std::vector<std::pair<std::string, int>> GetVendorPasswd(const std::string& passwd_file) {
     std::string passwd;
     if (!ReadFileToString(passwd_file, &passwd)) {
         return {};
@@ -70,6 +85,16 @@
     return result;
 }
 
+static std::vector<std::pair<std::string, int>> GetVendorPasswd() {
+    std::vector<std::pair<std::string, int>> result;
+    for (const auto& passwd_file : passwd_files) {
+        auto individual_result = GetVendorPasswd(passwd_file);
+        std::move(individual_result.begin(), individual_result.end(),
+                  std::back_insert_iterator(result));
+    }
+    return result;
+}
+
 passwd* getpwnam(const char* login) {  // NOLINT: implementing bad function.
     // This isn't thread safe, but that's okay for our purposes.
     static char static_name[32] = "";
@@ -118,41 +143,145 @@
 namespace android {
 namespace init {
 
-static Result<Success> do_stub(const BuiltinArguments& args) {
-    return Success();
+static Result<void> check_stub(const BuiltinArguments& args) {
+    return {};
 }
 
 #include "generated_stub_builtin_function_map.h"
 
+void PrintUsage() {
+    std::cout << "usage: host_init_verifier [options] <init rc file>\n"
+                 "\n"
+                 "Tests an init script for correctness\n"
+                 "\n"
+                 "-p FILE\tSearch this passwd file for users and groups\n"
+                 "--property_contexts=FILE\t Use this file for property_contexts\n"
+              << std::endl;
+}
+
+Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy() {
+    InterfaceInheritanceHierarchyMap result;
+    for (const HidlInterfaceMetadata& iface : HidlInterfaceMetadata::all()) {
+        std::set<FQName> inherited_interfaces;
+        for (const std::string& intf : iface.inherited) {
+            FQName fqname;
+            if (!fqname.setTo(intf)) {
+                return Error() << "Unable to parse interface '" << intf << "'";
+            }
+            inherited_interfaces.insert(fqname);
+        }
+        FQName fqname;
+        if (!fqname.setTo(iface.name)) {
+            return Error() << "Unable to parse interface '" << iface.name << "'";
+        }
+        result[fqname] = inherited_interfaces;
+    }
+
+    return result;
+}
+
+const PropertyInfoArea* property_info_area;
+
+void HandlePropertyContexts(const std::string& filename,
+                            std::vector<PropertyInfoEntry>* property_infos) {
+    auto file_contents = std::string();
+    if (!ReadFileToString(filename, &file_contents)) {
+        PLOG(ERROR) << "Could not read properties from '" << filename << "'";
+        exit(EXIT_FAILURE);
+    }
+
+    auto errors = std::vector<std::string>{};
+    ParsePropertyInfoFile(file_contents, true, property_infos, &errors);
+    for (const auto& error : errors) {
+        LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
+    }
+    if (!errors.empty()) {
+        exit(EXIT_FAILURE);
+    }
+}
+
 int main(int argc, char** argv) {
     android::base::InitLogging(argv, &android::base::StdioLogger);
     android::base::SetMinimumLogSeverity(android::base::ERROR);
 
-    if (argc != 2 && argc != 3) {
-        LOG(ERROR) << "Usage: " << argv[0] << " <init rc file> [passwd file]";
+    auto property_infos = std::vector<PropertyInfoEntry>();
+
+    while (true) {
+        static const char kPropertyContexts[] = "property-contexts=";
+        static const struct option long_options[] = {
+                {"help", no_argument, nullptr, 'h'},
+                {kPropertyContexts, required_argument, nullptr, 0},
+                {nullptr, 0, nullptr, 0},
+        };
+
+        int option_index;
+        int arg = getopt_long(argc, argv, "p:", long_options, &option_index);
+
+        if (arg == -1) {
+            break;
+        }
+
+        switch (arg) {
+            case 0:
+                if (long_options[option_index].name == kPropertyContexts) {
+                    HandlePropertyContexts(optarg, &property_infos);
+                }
+                break;
+            case 'h':
+                PrintUsage();
+                return EXIT_FAILURE;
+            case 'p':
+                passwd_files.emplace_back(optarg);
+                break;
+            default:
+                std::cerr << "getprop: getopt returned invalid result: " << arg << std::endl;
+                return EXIT_FAILURE;
+        }
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 1) {
+        PrintUsage();
         return EXIT_FAILURE;
     }
 
-    if (argc == 3) {
-        passwd_file = argv[2];
+    auto interface_inheritance_hierarchy_map = ReadInterfaceInheritanceHierarchy();
+    if (!interface_inheritance_hierarchy_map) {
+        LOG(ERROR) << interface_inheritance_hierarchy_map.error();
+        return EXIT_FAILURE;
+    }
+    SetKnownInterfaces(*interface_inheritance_hierarchy_map);
+
+    std::string serialized_contexts;
+    std::string trie_error;
+    if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_contexts,
+                   &trie_error)) {
+        LOG(ERROR) << "Unable to serialize property contexts: " << trie_error;
+        return EXIT_FAILURE;
     }
 
-    const BuiltinFunctionMap function_map;
+    property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_contexts.c_str());
+
+    const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
     Action::set_function_map(&function_map);
     ActionManager& am = ActionManager::GetInstance();
     ServiceList& sl = ServiceList::GetInstance();
     Parser parser;
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
+    parser.AddSectionParser("service", std::make_unique<ServiceParser>(
+                                               &sl, nullptr, *interface_inheritance_hierarchy_map));
     parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
     parser.AddSectionParser("import", std::make_unique<HostImportParser>());
 
-    if (!parser.ParseConfigFileInsecure(argv[1])) {
-        LOG(ERROR) << "Failed to open init rc script '" << argv[1] << "'";
+    if (!parser.ParseConfigFileInsecure(*argv)) {
+        LOG(ERROR) << "Failed to open init rc script '" << *argv << "'";
         return EXIT_FAILURE;
     }
-    if (parser.parse_error_count() > 0) {
-        LOG(ERROR) << "Failed to parse init script '" << argv[1] << "' with "
-                   << parser.parse_error_count() << " errors";
+    size_t failures = parser.parse_error_count() + am.CheckAllCommands() + sl.CheckAllCommands();
+    if (failures > 0) {
+        LOG(ERROR) << "Failed to parse init script '" << *argv << "' with " << failures
+                   << " errors";
         return EXIT_FAILURE;
     }
     return EXIT_SUCCESS;
diff --git a/init/boringssl_self_test.h b/init/host_init_verifier.h
similarity index 78%
rename from init/boringssl_self_test.h
rename to init/host_init_verifier.h
index b21fc78..5d24f2a 100644
--- a/init/boringssl_self_test.h
+++ b/init/host_init_verifier.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -16,13 +16,12 @@
 
 #pragma once
 
-#include "builtin_arguments.h"
-#include "result.h"
+#include <property_info_parser/property_info_parser.h>
 
 namespace android {
 namespace init {
 
-Result<Success> StartBoringSslSelfTest(const BuiltinArguments&);
+extern const android::properties::PropertyInfoArea* property_info_area;
 
 }  // namespace init
 }  // namespace android
diff --git a/init/import_parser.cpp b/init/import_parser.cpp
index fb3185e..1a43508 100644
--- a/init/import_parser.cpp
+++ b/init/import_parser.cpp
@@ -23,25 +23,24 @@
 namespace android {
 namespace init {
 
-Result<Success> ImportParser::ParseSection(std::vector<std::string>&& args,
-                                           const std::string& filename, int line) {
+Result<void> ImportParser::ParseSection(std::vector<std::string>&& args,
+                                        const std::string& filename, int line) {
     if (args.size() != 2) {
         return Error() << "single argument needed for import\n";
     }
 
-    std::string conf_file;
-    bool ret = expand_props(args[1], &conf_file);
-    if (!ret) {
-        return Error() << "error while expanding import";
+    auto conf_file = ExpandProps(args[1]);
+    if (!conf_file) {
+        return Error() << "Could not expand import: " << conf_file.error();
     }
 
-    LOG(INFO) << "Added '" << conf_file << "' to import list";
+    LOG(INFO) << "Added '" << *conf_file << "' to import list";
     if (filename_.empty()) filename_ = filename;
-    imports_.emplace_back(std::move(conf_file), line);
-    return Success();
+    imports_.emplace_back(std::move(*conf_file), line);
+    return {};
 }
 
-Result<Success> ImportParser::ParseLineSection(std::vector<std::string>&&, int) {
+Result<void> ImportParser::ParseLineSection(std::vector<std::string>&&, int) {
     return Error() << "Unexpected line found after import statement";
 }
 
diff --git a/init/import_parser.h b/init/import_parser.h
index 7bc72e6..5bf9c6c 100644
--- a/init/import_parser.h
+++ b/init/import_parser.h
@@ -28,9 +28,9 @@
 class ImportParser : public SectionParser {
   public:
     ImportParser(Parser* parser) : parser_(parser) {}
-    Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
-                                 int line) override;
-    Result<Success> ParseLineSection(std::vector<std::string>&&, int) override;
+    Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
+                              int line) override;
+    Result<void> ParseLineSection(std::vector<std::string>&&, int) override;
     void EndFile() override;
 
   private:
diff --git a/init/init.cpp b/init/init.cpp
index 6b03bc9..5f97e44 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -19,7 +19,6 @@
 #include <dirent.h>
 #include <fcntl.h>
 #include <pthread.h>
-#include <seccomp_policy.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,13 +27,19 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
+#include <functional>
 #include <map>
 #include <memory>
 #include <optional>
+#include <vector>
 
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
@@ -47,24 +52,27 @@
 #include <processgroup/setup.h>
 #include <selinux/android.h>
 
-#ifndef RECOVERY
-#include <binder/ProcessState.h>
-#endif
-
 #include "action_parser.h"
-#include "boringssl_self_test.h"
+#include "builtins.h"
 #include "epoll.h"
+#include "first_stage_init.h"
 #include "first_stage_mount.h"
 #include "import_parser.h"
 #include "keychords.h"
+#include "lmkd_service.h"
 #include "mount_handler.h"
 #include "mount_namespace.h"
 #include "property_service.h"
+#include "proto_utils.h"
 #include "reboot.h"
 #include "reboot_utils.h"
 #include "security.h"
+#include "selabel.h"
 #include "selinux.h"
+#include "service.h"
+#include "service_parser.h"
 #include "sigchld_handler.h"
+#include "system/core/init/property_service.pb.h"
 #include "util.h"
 
 using namespace std::chrono_literals;
@@ -73,6 +81,7 @@
 using android::base::boot_clock;
 using android::base::GetProperty;
 using android::base::ReadFileToString;
+using android::base::SetProperty;
 using android::base::StringPrintf;
 using android::base::Timer;
 using android::base::Trim;
@@ -83,23 +92,16 @@
 
 static int property_triggers_enabled = 0;
 
-static char qemu[32];
-
-std::string default_console = "/dev/console";
-
 static int signal_fd = -1;
+static int property_fd = -1;
 
 static std::unique_ptr<Timer> waiting_for_prop(nullptr);
 static std::string wait_prop_name;
 static std::string wait_prop_value;
-static bool shutting_down;
 static std::string shutdown_command;
 static bool do_shutdown = false;
-static bool load_debug_prop = false;
 
-std::vector<std::string> late_import_paths;
-
-static std::vector<Subcontext>* subcontexts;
+static std::unique_ptr<Subcontext> subcontext;
 
 void DumpState() {
     ServiceList::GetInstance().DumpState();
@@ -109,18 +111,22 @@
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
     Parser parser;
 
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
-    parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));
+    parser.AddSectionParser("service", std::make_unique<ServiceParser>(
+                                               &service_list, subcontext.get(), std::nullopt));
+    parser.AddSectionParser("on",
+                            std::make_unique<ActionParser>(&action_manager, subcontext.get()));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
     return parser;
 }
 
 // parser that only accepts new services
-Parser CreateServiceOnlyParser(ServiceList& service_list) {
+Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex) {
     Parser parser;
 
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
+    parser.AddSectionParser("service",
+                            std::make_unique<ServiceParser>(&service_list, subcontext.get(),
+                                                            std::nullopt, from_apex));
     return parser;
 }
 
@@ -129,16 +135,16 @@
 
     std::string bootscript = GetProperty("ro.boot.init_rc", "");
     if (bootscript.empty()) {
-        parser.ParseConfig("/init.rc");
+        parser.ParseConfig("/system/etc/init/hw/init.rc");
         if (!parser.ParseConfig("/system/etc/init")) {
             late_import_paths.emplace_back("/system/etc/init");
         }
+        // late_import is available only in Q and earlier release. As we don't
+        // have system_ext in those versions, skip late_import for system_ext.
+        parser.ParseConfig("/system_ext/etc/init");
         if (!parser.ParseConfig("/product/etc/init")) {
             late_import_paths.emplace_back("/product/etc/init");
         }
-        if (!parser.ParseConfig("/product_services/etc/init")) {
-            late_import_paths.emplace_back("/product_services/etc/init");
-        }
         if (!parser.ParseConfig("/odm/etc/init")) {
             late_import_paths.emplace_back("/odm/etc/init");
         }
@@ -173,6 +179,16 @@
     waiting_for_prop.reset();
 }
 
+static void TriggerShutdown(const std::string& command) {
+    // We can't call HandlePowerctlMessage() directly in this function,
+    // because it modifies the contents of the action queue, which can cause the action queue
+    // to get into a bad state if this function is called from a command being executed by the
+    // action queue.  Instead we set this flag and ensure that shutdown happens before the next
+    // command is run in the main init loop.
+    shutdown_command = command;
+    do_shutdown = true;
+}
+
 void property_changed(const std::string& name, const std::string& value) {
     // If the property is sys.powerctl, we bypass the event queue and immediately handle it.
     // This is to ensure that init will always and immediately shutdown/reboot, regardless of
@@ -181,20 +197,19 @@
     // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
     // commands to be executed.
     if (name == "sys.powerctl") {
-        // Despite the above comment, we can't call HandlePowerctlMessage() in this function,
-        // because it modifies the contents of the action queue, which can cause the action queue
-        // to get into a bad state if this function is called from a command being executed by the
-        // action queue.  Instead we set this flag and ensure that shutdown happens before the next
-        // command is run in the main init loop.
-        // TODO: once property service is removed from init, this will never happen from a builtin,
-        // but rather from a callback from the property service socket, in which case this hack can
-        // go away.
-        shutdown_command = value;
-        do_shutdown = true;
+        TriggerShutdown(value);
     }
 
     if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
 
+    // We always record how long init waited for ueventd to tell us cold boot finished.
+    // If we aren't waiting on this property, it means that ueventd finished before we even started
+    // to wait.
+    if (name == kColdBootDoneProp) {
+        auto time_waited = waiting_for_prop ? waiting_for_prop->duration().count() : 0;
+        SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
+    }
+
     if (waiting_for_prop) {
         if (wait_prop_name == name && wait_prop_value == value) {
             LOG(INFO) << "Wait for property '" << wait_prop_name << "=" << wait_prop_value
@@ -234,18 +249,18 @@
     return next_process_action_time;
 }
 
-static Result<Success> DoControlStart(Service* service) {
+static Result<void> DoControlStart(Service* service) {
     return service->Start();
 }
 
-static Result<Success> DoControlStop(Service* service) {
+static Result<void> DoControlStop(Service* service) {
     service->Stop();
-    return Success();
+    return {};
 }
 
-static Result<Success> DoControlRestart(Service* service) {
+static Result<void> DoControlRestart(Service* service) {
     service->Restart();
-    return Success();
+    return {};
 }
 
 enum class ControlTarget {
@@ -255,16 +270,16 @@
 
 struct ControlMessageFunction {
     ControlTarget target;
-    std::function<Result<Success>(Service*)> action;
+    std::function<Result<void>(Service*)> action;
 };
 
 static const std::map<std::string, ControlMessageFunction>& get_control_message_map() {
     // clang-format off
     static const std::map<std::string, ControlMessageFunction> control_message_functions = {
         {"sigstop_on",        {ControlTarget::SERVICE,
-                               [](auto* service) { service->set_sigstop(true); return Success(); }}},
+                               [](auto* service) { service->set_sigstop(true); return Result<void>{}; }}},
         {"sigstop_off",       {ControlTarget::SERVICE,
-                               [](auto* service) { service->set_sigstop(false); return Success(); }}},
+                               [](auto* service) { service->set_sigstop(false); return Result<void>{}; }}},
         {"start",             {ControlTarget::SERVICE,   DoControlStart}},
         {"stop",              {ControlTarget::SERVICE,   DoControlStop}},
         {"restart",           {ControlTarget::SERVICE,   DoControlRestart}},
@@ -277,13 +292,13 @@
     return control_message_functions;
 }
 
-void HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
+bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
     const auto& map = get_control_message_map();
     const auto it = map.find(msg);
 
     if (it == map.end()) {
         LOG(ERROR) << "Unknown control msg '" << msg << "'";
-        return;
+        return false;
     }
 
     std::string cmdline_path = StringPrintf("proc/%d/cmdline", pid);
@@ -295,9 +310,6 @@
         process_cmdline = "unknown process";
     }
 
-    LOG(INFO) << "Received control message '" << msg << "' for '" << name << "' from pid: " << pid
-              << " (" << process_cmdline << ")";
-
     const ControlMessageFunction& function = it->second;
 
     Service* svc = nullptr;
@@ -310,51 +322,37 @@
             svc = ServiceList::GetInstance().FindInterface(name);
             break;
         default:
-            LOG(ERROR) << "Invalid function target from static map key '" << msg << "': "
+            LOG(ERROR) << "Invalid function target from static map key ctl." << msg << ": "
                        << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
-            return;
+            return false;
     }
 
     if (svc == nullptr) {
-        LOG(ERROR) << "Could not find '" << name << "' for ctl." << msg;
-        return;
+        LOG(ERROR) << "Control message: Could not find '" << name << "' for ctl." << msg
+                   << " from pid: " << pid << " (" << process_cmdline << ")";
+        return false;
     }
 
     if (auto result = function.action(svc); !result) {
-        LOG(ERROR) << "Could not ctl." << msg << " for '" << name << "': " << result.error();
-    }
-}
-
-static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) {
-    Timer t;
-
-    LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "...";
-
-    // Historically we had a 1s timeout here because we weren't otherwise
-    // tracking boot time, and many OEMs made their sepolicy regular
-    // expressions too expensive (http://b/19899875).
-
-    // Now we're tracking boot time, just log the time taken to a system
-    // property. We still panic if it takes more than a minute though,
-    // because any build that slow isn't likely to boot at all, and we'd
-    // rather any test lab devices fail back to the bootloader.
-    if (wait_for_file(COLDBOOT_DONE, 60s) < 0) {
-        LOG(FATAL) << "Timed out waiting for " COLDBOOT_DONE;
+        LOG(ERROR) << "Control message: Could not ctl." << msg << " for '" << name
+                   << "' from pid: " << pid << " (" << process_cmdline << "): " << result.error();
+        return false;
     }
 
-    property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration().count()));
-    return Success();
+    LOG(INFO) << "Control message: Processed ctl." << msg << " for '" << name
+              << "' from pid: " << pid << " (" << process_cmdline << ")";
+    return true;
 }
 
-static Result<Success> console_init_action(const BuiltinArguments& args) {
-    std::string console = GetProperty("ro.boot.console", "");
-    if (!console.empty()) {
-        default_console = "/dev/" + console;
+static Result<void> wait_for_coldboot_done_action(const BuiltinArguments& args) {
+    if (!start_waiting_for_property(kColdBootDoneProp, "true")) {
+        LOG(FATAL) << "Could not wait for '" << kColdBootDoneProp << "'";
     }
-    return Success();
+
+    return {};
 }
 
-static Result<Success> SetupCgroupsAction(const BuiltinArguments&) {
+static Result<void> SetupCgroupsAction(const BuiltinArguments&) {
     // Have to create <CGROUPS_RC_DIR> using make_dir function
     // for appropriate sepolicy to be set for it
     make_dir(android::base::Dirname(CGROUPS_RC_PATH), 0711);
@@ -362,118 +360,30 @@
         return ErrnoError() << "Failed to setup cgroups";
     }
 
-    return Success();
-}
-
-static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {
-    if (key.empty()) return;
-
-    if (for_emulator) {
-        // In the emulator, export any kernel option with the "ro.kernel." prefix.
-        property_set("ro.kernel." + key, value);
-        return;
-    }
-
-    if (key == "qemu") {
-        strlcpy(qemu, value.c_str(), sizeof(qemu));
-    } else if (android::base::StartsWith(key, "androidboot.")) {
-        property_set("ro.boot." + key.substr(12), value);
-    }
+    return {};
 }
 
 static void export_oem_lock_status() {
     if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
         return;
     }
-    import_kernel_cmdline(
-            false, [](const std::string& key, const std::string& value, bool in_qemu) {
-                if (key == "androidboot.verifiedbootstate") {
-                    property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1");
-                }
-            });
-}
-
-static void export_kernel_boot_props() {
-    constexpr const char* UNSET = "";
-    struct {
-        const char *src_prop;
-        const char *dst_prop;
-        const char *default_value;
-    } prop_map[] = {
-        { "ro.boot.serialno",   "ro.serialno",   UNSET, },
-        { "ro.boot.mode",       "ro.bootmode",   "unknown", },
-        { "ro.boot.baseband",   "ro.baseband",   "unknown", },
-        { "ro.boot.bootloader", "ro.bootloader", "unknown", },
-        { "ro.boot.hardware",   "ro.hardware",   "unknown", },
-        { "ro.boot.revision",   "ro.revision",   "0", },
-    };
-    for (const auto& prop : prop_map) {
-        std::string value = GetProperty(prop.src_prop, prop.default_value);
-        if (value != UNSET)
-            property_set(prop.dst_prop, value);
-    }
-}
-
-static void process_kernel_dt() {
-    if (!is_android_dt_value_expected("compatible", "android,firmware")) {
-        return;
-    }
-
-    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(get_android_dt_dir().c_str()), closedir);
-    if (!dir) return;
-
-    std::string dt_file;
-    struct dirent *dp;
-    while ((dp = readdir(dir.get())) != NULL) {
-        if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") || !strcmp(dp->d_name, "name")) {
-            continue;
+    ImportKernelCmdline([](const std::string& key, const std::string& value) {
+        if (key == "androidboot.verifiedbootstate") {
+            SetProperty("ro.boot.flash.locked", value == "orange" ? "0" : "1");
         }
-
-        std::string file_name = get_android_dt_dir() + dp->d_name;
-
-        android::base::ReadFileToString(file_name, &dt_file);
-        std::replace(dt_file.begin(), dt_file.end(), ',', '.');
-
-        property_set("ro.boot."s + dp->d_name, dt_file);
-    }
+    });
 }
 
-static void process_kernel_cmdline() {
-    // The first pass does the common stuff, and finds if we are in qemu.
-    // The second pass is only necessary for qemu to export all kernel params
-    // as properties.
-    import_kernel_cmdline(false, import_kernel_nv);
-    if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
-}
-
-static Result<Success> property_enable_triggers_action(const BuiltinArguments& args) {
+static Result<void> property_enable_triggers_action(const BuiltinArguments& args) {
     /* Enable property triggers. */
     property_triggers_enabled = 1;
-    return Success();
+    return {};
 }
 
-static Result<Success> queue_property_triggers_action(const BuiltinArguments& args) {
+static Result<void> queue_property_triggers_action(const BuiltinArguments& args) {
     ActionManager::GetInstance().QueueBuiltinAction(property_enable_triggers_action, "enable_property_trigger");
     ActionManager::GetInstance().QueueAllPropertyActions();
-    return Success();
-}
-
-static Result<Success> InitBinder(const BuiltinArguments& args) {
-    // init's use of binder is very limited. init cannot:
-    //   - have any binder threads
-    //   - receive incoming binder calls
-    //   - pass local binder services to remote processes
-    //   - use death recipients
-    // The main supported usecases are:
-    //   - notifying other daemons (oneway calls only)
-    //   - retrieving data that is necessary to boot
-    // Also, binder can't be used by recovery.
-#ifndef RECOVERY
-    android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
-    android::ProcessState::self()->setCallRestriction(
-            ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY);
-#endif
-    return Success();
+    return {};
 }
 
 // Set the UDC controller for the ConfigFS USB Gadgets.
@@ -487,7 +397,7 @@
     while ((dp = readdir(dir.get())) != nullptr) {
         if (dp->d_name[0] == '.') continue;
 
-        property_set("sys.usb.controller", dp->d_name);
+        SetProperty("sys.usb.controller", dp->d_name);
         break;
     }
 }
@@ -600,18 +510,110 @@
     }
 }
 
-static void GlobalSeccomp() {
-    import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
-                                    bool in_qemu) {
-        if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
-            LOG(FATAL) << "Failed to globally enable seccomp!";
-        }
-    });
-}
-
 static void UmountDebugRamdisk() {
     if (umount("/debug_ramdisk") != 0) {
-        LOG(ERROR) << "Failed to umount /debug_ramdisk";
+        PLOG(ERROR) << "Failed to umount /debug_ramdisk";
+    }
+}
+
+static void MountExtraFilesystems() {
+#define CHECKCALL(x) \
+    if ((x) != 0) PLOG(FATAL) << #x " failed.";
+
+    // /apex is used to mount APEXes
+    CHECKCALL(mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+                    "mode=0755,uid=0,gid=0"));
+
+    // /linkerconfig is used to keep generated linker configuration
+    CHECKCALL(mount("tmpfs", "/linkerconfig", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+                    "mode=0755,uid=0,gid=0"));
+#undef CHECKCALL
+}
+
+static void RecordStageBoottimes(const boot_clock::time_point& second_stage_start_time) {
+    int64_t first_stage_start_time_ns = -1;
+    if (auto first_stage_start_time_str = getenv(kEnvFirstStageStartedAt);
+        first_stage_start_time_str) {
+        SetProperty("ro.boottime.init", first_stage_start_time_str);
+        android::base::ParseInt(first_stage_start_time_str, &first_stage_start_time_ns);
+    }
+    unsetenv(kEnvFirstStageStartedAt);
+
+    int64_t selinux_start_time_ns = -1;
+    if (auto selinux_start_time_str = getenv(kEnvSelinuxStartedAt); selinux_start_time_str) {
+        android::base::ParseInt(selinux_start_time_str, &selinux_start_time_ns);
+    }
+    unsetenv(kEnvSelinuxStartedAt);
+
+    if (selinux_start_time_ns == -1) return;
+    if (first_stage_start_time_ns == -1) return;
+
+    SetProperty("ro.boottime.init.first_stage",
+                std::to_string(selinux_start_time_ns - first_stage_start_time_ns));
+    SetProperty("ro.boottime.init.selinux",
+                std::to_string(second_stage_start_time.time_since_epoch().count() -
+                               selinux_start_time_ns));
+}
+
+void SendLoadPersistentPropertiesMessage() {
+    auto init_message = InitMessage{};
+    init_message.set_load_persistent_properties(true);
+    if (auto result = SendMessage(property_fd, init_message); !result) {
+        LOG(ERROR) << "Failed to send load persistent properties message: " << result.error();
+    }
+}
+
+void SendStopSendingMessagesMessage() {
+    auto init_message = InitMessage{};
+    init_message.set_stop_sending_messages(true);
+    if (auto result = SendMessage(property_fd, init_message); !result) {
+        LOG(ERROR) << "Failed to send 'stop sending messages' message: " << result.error();
+    }
+}
+
+void SendStartSendingMessagesMessage() {
+    auto init_message = InitMessage{};
+    init_message.set_start_sending_messages(true);
+    if (auto result = SendMessage(property_fd, init_message); !result) {
+        LOG(ERROR) << "Failed to send 'start sending messages' message: " << result.error();
+    }
+}
+
+static void HandlePropertyFd() {
+    auto message = ReadMessage(property_fd);
+    if (!message) {
+        LOG(ERROR) << "Could not read message from property service: " << message.error();
+        return;
+    }
+
+    auto property_message = PropertyMessage{};
+    if (!property_message.ParseFromString(*message)) {
+        LOG(ERROR) << "Could not parse message from property service";
+        return;
+    }
+
+    switch (property_message.msg_case()) {
+        case PropertyMessage::kControlMessage: {
+            auto& control_message = property_message.control_message();
+            bool success = HandleControlMessage(control_message.msg(), control_message.name(),
+                                                control_message.pid());
+
+            uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+            if (control_message.has_fd()) {
+                int fd = control_message.fd();
+                TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0));
+                close(fd);
+            }
+            break;
+        }
+        case PropertyMessage::kChangedMessage: {
+            auto& changed_message = property_message.changed_message();
+            property_changed(changed_message.name(), changed_message.value());
+            break;
+        }
+        default:
+            LOG(ERROR) << "Unknown message type from property service: "
+                       << property_message.msg_case();
     }
 }
 
@@ -620,17 +622,24 @@
         InstallRebootSignalHandlers();
     }
 
+    boot_clock::time_point start_time = boot_clock::now();
+
+    trigger_shutdown = TriggerShutdown;
+
     SetStdioToDevNull(argv);
     InitKernelLogging(argv);
     LOG(INFO) << "init second stage started!";
 
-    // Set init and its forked children's oom_adj.
-    if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) {
-        LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error();
-    }
+    // Will handle EPIPE at the time of write by checking the errno
+    signal(SIGPIPE, SIG_IGN);
 
-    // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
-    GlobalSeccomp();
+    // Set init and its forked children's oom_adj.
+    if (auto result =
+                WriteFile("/proc/1/oom_score_adj", StringPrintf("%d", DEFAULT_OOM_SCORE_ADJUST));
+        !result) {
+        LOG(ERROR) << "Unable to write " << DEFAULT_OOM_SCORE_ADJUST
+                   << " to /proc/1/oom_score_adj: " << result.error();
+    }
 
     // Set up a session keyring that all processes will have access to. It
     // will hold things like FBE encryption keys. No process should override
@@ -640,37 +649,30 @@
     // Indicate that booting is in progress to background fw loaders, etc.
     close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
 
-    property_init();
-
-    // If arguments are passed both on the command line and in DT,
-    // properties set in DT always have priority over the command-line ones.
-    process_kernel_dt();
-    process_kernel_cmdline();
-
-    // Propagate the kernel variables to internal variables
-    // used by init as well as the current required properties.
-    export_kernel_boot_props();
-
-    // Make the time that init started available for bootstat to log.
-    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
-    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
-
-    // Set libavb version for Framework-only OTA match in Treble build.
-    const char* avb_version = getenv("INIT_AVB_VERSION");
-    if (avb_version) property_set("ro.boot.avb_version", avb_version);
-
     // See if need to load debug props to allow adb root, when the device is unlocked.
     const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
+    bool load_debug_prop = false;
     if (force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {
         load_debug_prop = "true"s == force_debuggable_env;
     }
-
-    // Clean up our environment.
-    unsetenv("INIT_STARTED_AT");
-    unsetenv("INIT_SELINUX_TOOK");
-    unsetenv("INIT_AVB_VERSION");
     unsetenv("INIT_FORCE_DEBUGGABLE");
 
+    // Umount the debug ramdisk so property service doesn't read .prop files from there, when it
+    // is not meant to.
+    if (!load_debug_prop) {
+        UmountDebugRamdisk();
+    }
+
+    PropertyInit();
+
+    // Umount the debug ramdisk after property service has read the .prop files when it means to.
+    if (load_debug_prop) {
+        UmountDebugRamdisk();
+    }
+
+    // Mount extra filesystems required during second stage init
+    MountExtraFilesystems();
+
     // Now set up SELinux for second stage.
     SelinuxSetupKernelLogging();
     SelabelInitialize();
@@ -683,22 +685,33 @@
 
     InstallSignalFdHandler(&epoll);
 
-    property_load_boot_defaults(load_debug_prop);
-    UmountDebugRamdisk();
+    StartPropertyService(&property_fd);
+    if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) {
+        LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
+    }
+
+    // Make the time that init stages started available for bootstat to log.
+    RecordStageBoottimes(start_time);
+
+    // Set libavb version for Framework-only OTA match in Treble build.
+    if (const char* avb_version = getenv("INIT_AVB_VERSION"); avb_version != nullptr) {
+        SetProperty("ro.boot.avb_version", avb_version);
+    }
+    unsetenv("INIT_AVB_VERSION");
+
     fs_mgr_vendor_overlay_mount_all();
     export_oem_lock_status();
-    StartPropertyService(&epoll);
     MountHandler mount_handler(&epoll);
     set_usb_controller();
 
-    const BuiltinFunctionMap function_map;
+    const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
     Action::set_function_map(&function_map);
 
     if (!SetupMountNamespaces()) {
         PLOG(FATAL) << "SetupMountNamespaces failed";
     }
 
-    subcontexts = InitializeSubcontexts();
+    subcontext = InitializeSubcontext();
 
     ActionManager& am = ActionManager::GetInstance();
     ServiceList& sm = ServiceList::GetInstance();
@@ -711,13 +724,14 @@
 
     // Make the GSI status available before scripts start running.
     if (android::gsi::IsGsiRunning()) {
-        property_set("ro.gsid.image_running", "1");
+        SetProperty("ro.gsid.image_running", "1");
     } else {
-        property_set("ro.gsid.image_running", "0");
+        SetProperty("ro.gsid.image_running", "0");
     }
 
     am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
 
+    am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
     am.QueueEventTrigger("early-init");
 
     // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
@@ -725,32 +739,24 @@
     // ... so that we can start queuing up actions that require stuff from /dev.
     am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
     am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
-    am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
     Keychords keychords;
     am.QueueBuiltinAction(
-        [&epoll, &keychords](const BuiltinArguments& args) -> Result<Success> {
-            for (const auto& svc : ServiceList::GetInstance()) {
-                keychords.Register(svc->keycodes());
-            }
-            keychords.Start(&epoll, HandleKeychord);
-            return Success();
-        },
-        "KeychordInit");
-    am.QueueBuiltinAction(console_init_action, "console_init");
+            [&epoll, &keychords](const BuiltinArguments& args) -> Result<void> {
+                for (const auto& svc : ServiceList::GetInstance()) {
+                    keychords.Register(svc->keycodes());
+                }
+                keychords.Start(&epoll, HandleKeychord);
+                return {};
+            },
+            "KeychordInit");
 
     // Trigger all the boot actions to get us started.
     am.QueueEventTrigger("init");
 
-    // Starting the BoringSSL self test, for NIAP certification compliance.
-    am.QueueBuiltinAction(StartBoringSslSelfTest, "StartBoringSslSelfTest");
-
     // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
     // wasn't ready immediately after wait_for_coldboot_done
     am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
 
-    // Initialize binder before bringing up other system services
-    am.QueueBuiltinAction(InitBinder, "InitBinder");
-
     // Don't mount filesystems or start core system services in charger mode.
     std::string bootmode = GetProperty("ro.bootmode", "");
     if (bootmode == "charger") {
@@ -766,18 +772,16 @@
         // By default, sleep until something happens.
         auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
 
-        if (do_shutdown && !shutting_down) {
+        if (do_shutdown && !IsShuttingDown()) {
             do_shutdown = false;
-            if (HandlePowerctlMessage(shutdown_command)) {
-                shutting_down = true;
-            }
+            HandlePowerctlMessage(shutdown_command);
         }
 
         if (!(waiting_for_prop || Service::is_exec_service_running())) {
             am.ExecuteOneCommand();
         }
         if (!(waiting_for_prop || Service::is_exec_service_running())) {
-            if (!shutting_down) {
+            if (!IsShuttingDown()) {
                 auto next_process_action_time = HandleProcessActions();
 
                 // If there's a process that needs restarting, wake up in time for that.
@@ -792,8 +796,17 @@
             if (am.HasMoreCommands()) epoll_timeout = 0ms;
         }
 
-        if (auto result = epoll.Wait(epoll_timeout); !result) {
-            LOG(ERROR) << result.error();
+        auto pending_functions = epoll.Wait(epoll_timeout);
+        if (!pending_functions) {
+            LOG(ERROR) << pending_functions.error();
+        } else if (!pending_functions->empty()) {
+            // We always reap children before responding to the other pending functions. This is to
+            // prevent a race where other daemons see that a service has exited and ask init to
+            // start it again via ctl.start before init has reaped it.
+            ReapAnyOutstandingChildren();
+            for (const auto& function : *pending_functions) {
+                (*function)();
+            }
         }
     }
 
diff --git a/init/init.h b/init/init.h
index a76da20..4bbca6f 100644
--- a/init/init.h
+++ b/init/init.h
@@ -14,35 +14,22 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_INIT_H
-#define _INIT_INIT_H
+#pragma once
 
 #include <sys/types.h>
 
-#include <functional>
 #include <string>
-#include <vector>
 
 #include "action.h"
 #include "action_manager.h"
 #include "parser.h"
-#include "service.h"
+#include "service_list.h"
 
 namespace android {
 namespace init {
 
-// Note: These globals are *only* valid in init, so they should not be used in ueventd
-// or any files that may be included in ueventd, such as devices.cpp and util.cpp.
-// TODO: Have an Init class and remove all globals.
-extern std::string default_console;
-extern std::vector<std::string> late_import_paths;
-
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
-Parser CreateServiceOnlyParser(ServiceList& service_list);
-
-void HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid);
-
-void property_changed(const std::string& name, const std::string& value);
+Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex);
 
 bool start_waiting_for_property(const char *name, const char *value);
 
@@ -50,9 +37,11 @@
 
 void ResetWaitForProp();
 
+void SendLoadPersistentPropertiesMessage();
+void SendStopSendingMessagesMessage();
+void SendStartSendingMessagesMessage();
+
 int SecondStageMain(int argc, char** argv);
 
 }  // namespace init
 }  // namespace android
-
-#endif  /* _INIT_INIT_H */
diff --git a/init/init_test.cpp b/init/init_test.cpp
index c2f0c41..9f63e4f 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -22,12 +22,14 @@
 #include "action.h"
 #include "action_manager.h"
 #include "action_parser.h"
+#include "builtin_arguments.h"
 #include "builtins.h"
 #include "import_parser.h"
 #include "keyword_map.h"
 #include "parser.h"
 #include "service.h"
-#include "test_function_map.h"
+#include "service_list.h"
+#include "service_parser.h"
 #include "util.h"
 
 namespace android {
@@ -35,14 +37,15 @@
 
 using ActionManagerCommand = std::function<void(ActionManager&)>;
 
-void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map,
+void TestInit(const std::string& init_script_file, const BuiltinFunctionMap& test_function_map,
               const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
     ActionManager am;
 
     Action::set_function_map(&test_function_map);
 
     Parser parser;
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(service_list, nullptr));
+    parser.AddSectionParser("service",
+                            std::make_unique<ServiceParser>(service_list, nullptr, std::nullopt));
     parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
@@ -57,7 +60,7 @@
     }
 }
 
-void TestInitText(const std::string& init_script, const TestFunctionMap& test_function_map,
+void TestInitText(const std::string& init_script, const BuiltinFunctionMap& test_function_map,
                   const std::vector<ActionManagerCommand>& commands, ServiceList* service_list) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
@@ -73,8 +76,13 @@
 pass_test
 )init";
 
-    TestFunctionMap test_function_map;
-    test_function_map.Add("pass_test", [&expect_true]() { expect_true = true; });
+    auto do_pass_test = [&expect_true](const BuiltinArguments&) {
+        expect_true = true;
+        return Result<void>{};
+    };
+    BuiltinFunctionMap test_function_map = {
+            {"pass_test", {0, 0, {false, do_pass_test}}},
+    };
 
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
@@ -85,6 +93,26 @@
     EXPECT_TRUE(expect_true);
 }
 
+TEST(init, WrongEventTrigger) {
+    std::string init_script =
+            R"init(
+on boot:
+pass_test
+)init";
+
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    ASSERT_TRUE(android::base::WriteStringToFd(init_script, tf.fd));
+
+    ActionManager am;
+
+    Parser parser;
+    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
+
+    ASSERT_TRUE(parser.ParseConfig(tf.path));
+    ASSERT_EQ(1u, parser.parse_error_count());
+}
+
 TEST(init, EventTriggerOrder) {
     std::string init_script =
         R"init(
@@ -100,10 +128,24 @@
 )init";
 
     int num_executed = 0;
-    TestFunctionMap test_function_map;
-    test_function_map.Add("execute_first", [&num_executed]() { EXPECT_EQ(0, num_executed++); });
-    test_function_map.Add("execute_second", [&num_executed]() { EXPECT_EQ(1, num_executed++); });
-    test_function_map.Add("execute_third", [&num_executed]() { EXPECT_EQ(2, num_executed++); });
+    auto do_execute_first = [&num_executed](const BuiltinArguments&) {
+        EXPECT_EQ(0, num_executed++);
+        return Result<void>{};
+    };
+    auto do_execute_second = [&num_executed](const BuiltinArguments&) {
+        EXPECT_EQ(1, num_executed++);
+        return Result<void>{};
+    };
+    auto do_execute_third = [&num_executed](const BuiltinArguments&) {
+        EXPECT_EQ(2, num_executed++);
+        return Result<void>{};
+    };
+
+    BuiltinFunctionMap test_function_map = {
+            {"execute_first", {0, 0, {false, do_execute_first}}},
+            {"execute_second", {0, 0, {false, do_execute_second}}},
+            {"execute_third", {0, 0, {false, do_execute_third}}},
+    };
 
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
@@ -124,7 +166,7 @@
 )init";
 
     ServiceList service_list;
-    TestInitText(init_script, TestFunctionMap(), {}, &service_list);
+    TestInitText(init_script, BuiltinFunctionMap(), {}, &service_list);
     ASSERT_EQ(1, std::distance(service_list.begin(), service_list.end()));
 
     auto service = service_list.begin()->get();
@@ -180,11 +222,12 @@
     auto execute_command = [&num_executed](const BuiltinArguments& args) {
         EXPECT_EQ(2U, args.size());
         EXPECT_EQ(++num_executed, std::stoi(args[1]));
-        return Success();
+        return Result<void>{};
     };
 
-    TestFunctionMap test_function_map;
-    test_function_map.Add("execute", 1, 1, false, execute_command);
+    BuiltinFunctionMap test_function_map = {
+            {"execute", {1, 1, {false, execute_command}}},
+    };
 
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
@@ -198,3 +241,19 @@
 
 }  // namespace init
 }  // namespace android
+
+int SubcontextTestChildMain(int, char**);
+int FirmwareTestChildMain(int, char**);
+
+int main(int argc, char** argv) {
+    if (argc > 1 && !strcmp(argv[1], "subcontext")) {
+        return SubcontextTestChildMain(argc, argv);
+    }
+
+    if (argc > 1 && !strcmp(argv[1], "firmware")) {
+        return FirmwareTestChildMain(argc, argv);
+    }
+
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/init/interface_utils.cpp b/init/interface_utils.cpp
new file mode 100644
index 0000000..1b76bba
--- /dev/null
+++ b/init/interface_utils.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 "interface_utils.h"
+
+#include <fstream>
+#include <sstream>
+
+#include <android-base/strings.h>
+#include <hidl-util/FqInstance.h>
+
+using android::FqInstance;
+using android::FQName;
+using android::base::Error;
+
+namespace android {
+namespace init {
+
+namespace {
+
+std::string FQNamesToString(const std::set<FQName>& fqnames) {
+    std::set<std::string> fqname_strings;
+    for (const FQName& fqname : fqnames) {
+        fqname_strings.insert(fqname.string());
+    }
+    return android::base::Join(fqname_strings, " ");
+}
+
+}  // namespace
+
+Result<void> CheckInterfaceInheritanceHierarchy(const std::set<std::string>& instances,
+                                                const InterfaceInheritanceHierarchyMap& hierarchy) {
+    std::set<FQName> interface_fqnames;
+    for (const std::string& instance : instances) {
+        // There is insufficient build-time information on AIDL interfaces to check them here
+        // TODO(b/139307527): Rework how services store interfaces to avoid excess string parsing
+        if (base::Split(instance, "/")[0] == "aidl") {
+            continue;
+        }
+
+        FqInstance fqinstance;
+        if (!fqinstance.setTo(instance)) {
+            return Error() << "Unable to parse interface instance '" << instance << "'";
+        }
+        interface_fqnames.insert(fqinstance.getFqName());
+    }
+    return CheckInterfaceInheritanceHierarchy(interface_fqnames, hierarchy);
+}
+
+Result<void> CheckInterfaceInheritanceHierarchy(const std::set<FQName>& interfaces,
+                                                const InterfaceInheritanceHierarchyMap& hierarchy) {
+    std::ostringstream error_stream;
+    for (const FQName& intf : interfaces) {
+        if (hierarchy.count(intf) == 0) {
+            error_stream << "\nInterface is not in the known set of hidl_interfaces: '"
+                         << intf.string()
+                         << "'. Please ensure the interface is spelled correctly and built "
+                         << "by a hidl_interface target.";
+            continue;
+        }
+        const std::set<FQName>& required_interfaces = hierarchy.at(intf);
+        std::set<FQName> diff;
+        std::set_difference(required_interfaces.begin(), required_interfaces.end(),
+                            interfaces.begin(), interfaces.end(),
+                            std::inserter(diff, diff.begin()));
+        if (!diff.empty()) {
+            error_stream << "\nInterface '" << intf.string() << "' requires its full inheritance "
+                         << "hierarchy to be listed in this init_rc file. Missing "
+                         << "interfaces: [" << FQNamesToString(diff) << "]";
+        }
+    }
+    const std::string& errors = error_stream.str();
+    if (!errors.empty()) {
+        return Error() << errors;
+    }
+
+    return {};
+}
+
+std::optional<std::set<FQName>> known_interfaces;
+
+void SetKnownInterfaces(const InterfaceInheritanceHierarchyMap& hierarchy) {
+    known_interfaces = std::set<FQName>();
+    for (const auto& [intf, inherited_interfaces] : hierarchy) {
+        known_interfaces->insert(intf);
+    }
+}
+
+Result<void> IsKnownInterface(const std::string& instance) {
+    FqInstance fqinstance;
+    if (!fqinstance.setTo(instance)) {
+        return Error() << "Unable to parse interface instance '" << instance << "'";
+    }
+    return IsKnownInterface(fqinstance.getFqName());
+}
+
+Result<void> IsKnownInterface(const FQName& intf) {
+    if (!known_interfaces) {
+        return Error() << "No known interfaces have been loaded.";
+    }
+    if (known_interfaces->count(intf) == 0) {
+        return Error() << "Interface is not in the known set of hidl_interfaces: '" << intf.string()
+                       << "'. Please ensure the interface is spelled correctly and built "
+                       << "by a hidl_interface target.";
+    }
+    return {};
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/interface_utils.h b/init/interface_utils.h
new file mode 100644
index 0000000..4ca377f
--- /dev/null
+++ b/init/interface_utils.h
@@ -0,0 +1,50 @@
+/*
+ * 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 <map>
+#include <set>
+#include <string>
+
+#include <hidl-util/FQName.h>
+
+#include "result.h"
+
+namespace android {
+namespace init {
+
+using InterfaceInheritanceHierarchyMap = std::map<android::FQName, std::set<android::FQName>>;
+
+// For the given set of interfaces / interface instances, checks that each
+// interface's hierarchy of inherited interfaces is also included in the given
+// interface set. Uses the provided hierarchy data.
+Result<void> CheckInterfaceInheritanceHierarchy(const std::set<std::string>& instances,
+                                                const InterfaceInheritanceHierarchyMap& hierarchy);
+Result<void> CheckInterfaceInheritanceHierarchy(const std::set<android::FQName>& interfaces,
+                                                const InterfaceInheritanceHierarchyMap& hierarchy);
+
+// Saves the set of known interfaces using the provided HIDL interface
+// inheritance hierarchy.
+void SetKnownInterfaces(const InterfaceInheritanceHierarchyMap& hierarchy);
+
+// Checks if the provided interface is in the set of known interfaces. Returns
+// an empty Result if present, otherwise an Error.
+Result<void> IsKnownInterface(const std::string& instance);
+Result<void> IsKnownInterface(const FQName& intf);
+
+}  // namespace init
+}  // namespace android
diff --git a/init/keychords.cpp b/init/keychords.cpp
index f5ac44f..5f2682b 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -41,7 +41,7 @@
 
 Keychords::~Keychords() noexcept {
     if (inotify_fd_ >= 0) {
-        epoll_->UnregisterHandler(inotify_fd_).IgnoreError();
+        epoll_->UnregisterHandler(inotify_fd_);
         ::close(inotify_fd_);
     }
     while (!registration_.empty()) GeteventCloseDevice(registration_.begin()->first);
@@ -212,7 +212,7 @@
     auto it = registration_.find(device);
     if (it == registration_.end()) return;
     auto fd = (*it).second;
-    epoll_->UnregisterHandler(fd).IgnoreError();
+    epoll_->UnregisterHandler(fd);
     registration_.erase(it);
     ::close(fd);
 }
@@ -285,7 +285,7 @@
 
 void Keychords::Start(Epoll* epoll, std::function<void(const std::vector<int>&)> handler) {
     epoll_ = epoll;
-    handler_ = handler;
+    handler_ = std::move(handler);
     if (entries_.size()) GeteventOpenDevice();
 }
 
diff --git a/init/keychords_test.cpp b/init/keychords_test.cpp
index e5a6fd3..6e9b337 100644
--- a/init/keychords_test.cpp
+++ b/init/keychords_test.cpp
@@ -29,7 +29,6 @@
 #include <vector>
 
 #include <android-base/properties.h>
-#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <gtest/gtest.h>
 
@@ -213,7 +212,11 @@
 }
 
 void TestFrame::RelaxForMs(std::chrono::milliseconds wait) {
-    epoll_.Wait(wait).IgnoreError();
+    auto pending_functions = epoll_.Wait(wait);
+    ASSERT_TRUE(pending_functions) << pending_functions.error();
+    for (const auto& function : *pending_functions) {
+        (*function)();
+    }
 }
 
 void TestFrame::SetChord(int key, bool value) {
diff --git a/init/keyword_map.h b/init/keyword_map.h
index c95fc73..d92678f 100644
--- a/init/keyword_map.h
+++ b/init/keyword_map.h
@@ -14,70 +14,74 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_KEYWORD_MAP_H_
-#define _INIT_KEYWORD_MAP_H_
+#pragma once
 
 #include <map>
 #include <string>
-
-#include <android-base/stringprintf.h>
+#include <vector>
 
 #include "result.h"
 
 namespace android {
 namespace init {
 
-template <typename Function>
+// Every init builtin, init service option, and ueventd option has a minimum and maximum number of
+// arguments.  These must be checked both at run time for safety and also at build time for
+// correctness in host_init_verifier.  Instead of copying and pasting the boiler plate code that
+// does this check into each function, it is abstracted in KeywordMap<>.  This class maps keywords
+// to functions and checks that the number of arguments provided falls in the correct range or
+// returns an error otherwise.
+
+// Value is the return value of Find(), which is typically either a single function or a struct with
+// additional information.
+template <typename Value>
 class KeywordMap {
   public:
-    using FunctionInfo = std::tuple<std::size_t, std::size_t, Function>;
-    using Map = std::map<std::string, FunctionInfo>;
+    struct MapValue {
+        size_t min_args;
+        size_t max_args;
+        Value value;
+    };
 
-    virtual ~KeywordMap() {
-    }
+    KeywordMap() {}
+    KeywordMap(std::initializer_list<std::pair<const std::string, MapValue>> init) : map_(init) {}
 
-    const Result<Function> FindFunction(const std::vector<std::string>& args) const {
-        using android::base::StringPrintf;
-
+    Result<Value> Find(const std::vector<std::string>& args) const {
         if (args.empty()) return Error() << "Keyword needed, but not provided";
 
         auto& keyword = args[0];
         auto num_args = args.size() - 1;
 
-        auto function_info_it = map().find(keyword);
-        if (function_info_it == map().end()) {
-            return Error() << StringPrintf("Invalid keyword '%s'", keyword.c_str());
+        auto result_it = map_.find(keyword);
+        if (result_it == map_.end()) {
+            return Errorf("Invalid keyword '{}'", keyword);
         }
 
-        auto function_info = function_info_it->second;
+        auto result = result_it->second;
 
-        auto min_args = std::get<0>(function_info);
-        auto max_args = std::get<1>(function_info);
+        auto min_args = result.min_args;
+        auto max_args = result.max_args;
         if (min_args == max_args && num_args != min_args) {
-            return Error() << StringPrintf("%s requires %zu argument%s", keyword.c_str(), min_args,
-                                           (min_args > 1 || min_args == 0) ? "s" : "");
+            return Errorf("{} requires {} argument{}", keyword, min_args,
+                          (min_args > 1 || min_args == 0) ? "s" : "");
         }
 
         if (num_args < min_args || num_args > max_args) {
             if (max_args == std::numeric_limits<decltype(max_args)>::max()) {
-                return Error() << StringPrintf("%s requires at least %zu argument%s",
-                                               keyword.c_str(), min_args, min_args > 1 ? "s" : "");
+                return Errorf("{} requires at least {} argument{}", keyword, min_args,
+                              min_args > 1 ? "s" : "");
             } else {
-                return Error() << StringPrintf("%s requires between %zu and %zu arguments",
-                                               keyword.c_str(), min_args, max_args);
+                return Errorf("{} requires between {} and {} arguments", keyword, min_args,
+                              max_args);
             }
         }
 
-        return std::get<Function>(function_info);
+        return result.value;
     }
 
   private:
-    // Map of keyword ->
-    // (minimum number of arguments, maximum number of arguments, function pointer)
-    virtual const Map& map() const = 0;
+    std::map<std::string, MapValue> map_;
 };
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/lmkd_service.cpp b/init/lmkd_service.cpp
new file mode 100644
index 0000000..dd1ab4d
--- /dev/null
+++ b/init/lmkd_service.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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 "lmkd_service.h"
+
+#include <errno.h>
+
+#include <android-base/logging.h>
+#include <liblmkd_utils.h>
+
+#include "service_list.h"
+
+namespace android {
+namespace init {
+
+enum LmkdRegistrationResult {
+    LMKD_REG_SUCCESS,
+    LMKD_CONN_FAILED,
+    LMKD_REG_FAILED,
+};
+
+static int lmkd_socket = -1;
+
+static LmkdRegistrationResult RegisterProcess(uid_t uid, pid_t pid, int oom_score_adjust) {
+    // connect to lmkd if not already connected
+    if (lmkd_socket < 0) {
+        lmkd_socket = lmkd_connect();
+        if (lmkd_socket < 0) {
+            return LMKD_CONN_FAILED;
+        }
+    }
+
+    // register service with lmkd
+    struct lmk_procprio params;
+    params.pid = pid;
+    params.uid = uid;
+    params.oomadj = oom_score_adjust;
+    params.ptype = PROC_TYPE_SERVICE;
+    if (lmkd_register_proc(lmkd_socket, &params) != 0) {
+        // data transfer failed, reset the connection
+        close(lmkd_socket);
+        lmkd_socket = -1;
+        return LMKD_REG_FAILED;
+    }
+
+    return LMKD_REG_SUCCESS;
+}
+
+static bool UnregisterProcess(pid_t pid) {
+    if (lmkd_socket < 0) {
+        // no connection or it was lost, no need to unregister
+        return false;
+    }
+
+    // unregister service
+    struct lmk_procremove params;
+    params.pid = pid;
+    if (lmkd_unregister_proc(lmkd_socket, &params) != 0) {
+        // data transfer failed, reset the connection
+        close(lmkd_socket);
+        lmkd_socket = -1;
+        return false;
+    }
+
+    return true;
+}
+
+static void RegisterServices(pid_t exclude_pid) {
+    for (const auto& service : ServiceList::GetInstance().services()) {
+        auto svc = service.get();
+        if (svc->oom_score_adjust() != DEFAULT_OOM_SCORE_ADJUST) {
+            // skip if process is excluded or not yet forked (pid==0)
+            if (svc->pid() == exclude_pid || svc->pid() == 0) {
+                continue;
+            }
+            if (RegisterProcess(svc->uid(), svc->pid(), svc->oom_score_adjust()) !=
+                LMKD_REG_SUCCESS) {
+                // a failure here resets the connection, will retry during next registration
+                break;
+            }
+        }
+    }
+}
+
+void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust) {
+    bool new_connection = lmkd_socket == -1;
+    LmkdRegistrationResult result;
+
+    result = RegisterProcess(uid, pid, oom_score_adjust);
+    if (result == LMKD_REG_FAILED) {
+        // retry one time if connection to lmkd was lost
+        result = RegisterProcess(uid, pid, oom_score_adjust);
+        new_connection = result == LMKD_REG_SUCCESS;
+    }
+    switch (result) {
+        case LMKD_REG_SUCCESS:
+            // register existing services once new connection is established
+            if (new_connection) {
+                RegisterServices(pid);
+            }
+            break;
+        case LMKD_CONN_FAILED:
+            PLOG(ERROR) << "lmkd connection failed when " << name << " process got started";
+            break;
+        case LMKD_REG_FAILED:
+            PLOG(ERROR) << "lmkd failed to register " << name << " process";
+            break;
+    }
+}
+
+void LmkdUnregister(const std::string& name, pid_t pid) {
+    if (!UnregisterProcess(pid)) {
+        PLOG(ERROR) << "lmkd failed to unregister " << name << " process";
+    }
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/lmkd_service.h b/init/lmkd_service.h
new file mode 100644
index 0000000..5b51d52
--- /dev/null
+++ b/init/lmkd_service.h
@@ -0,0 +1,44 @@
+/*
+ * 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 <string>
+
+namespace android {
+namespace init {
+
+static const int MIN_OOM_SCORE_ADJUST = -1000;
+static const int MAX_OOM_SCORE_ADJUST = 1000;
+// service with default score is unkillable
+static const int DEFAULT_OOM_SCORE_ADJUST = MIN_OOM_SCORE_ADJUST;
+
+#if defined(__ANDROID__)
+
+void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust);
+void LmkdUnregister(const std::string& name, pid_t pid);
+
+#else  // defined(__ANDROID__)
+
+static inline void LmkdRegister(const std::string&, uid_t, pid_t, int) {}
+static inline void LmkdUnregister(const std::string&, pid_t) {}
+
+#endif  // defined(__ANDROID__)
+
+}  // namespace init
+}  // namespace android
diff --git a/init/main.cpp b/init/main.cpp
index 2ce46ef..38bc74b 100644
--- a/init/main.cpp
+++ b/init/main.cpp
@@ -60,7 +60,7 @@
     if (argc > 1) {
         if (!strcmp(argv[1], "subcontext")) {
             android::base::InitLogging(argv, &android::base::KernelLogger);
-            const BuiltinFunctionMap function_map;
+            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
 
             return SubcontextMain(argc, argv, &function_map);
         }
diff --git a/init/modalias_handler.cpp b/init/modalias_handler.cpp
index c61c210..07b05d8 100644
--- a/init/modalias_handler.cpp
+++ b/init/modalias_handler.cpp
@@ -16,147 +16,20 @@
 
 #include "modalias_handler.h"
 
-#include <fnmatch.h>
-#include <sys/syscall.h>
-
-#include <algorithm>
-#include <functional>
 #include <string>
 #include <vector>
 
-#include <android-base/chrono_utils.h>
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-
-#include "parser.h"
+#include <modprobe/modprobe.h>
 
 namespace android {
 namespace init {
 
-Result<Success> ModaliasHandler::ParseDepCallback(std::vector<std::string>&& args) {
-    std::vector<std::string> deps;
-
-    // Set first item as our modules path
-    std::string::size_type pos = args[0].find(':');
-    if (pos != std::string::npos) {
-        deps.emplace_back(args[0].substr(0, pos));
-    } else {
-        return Error() << "dependency lines must start with name followed by ':'";
-    }
-
-    // Remaining items are dependencies of our module
-    for (auto arg = args.begin() + 1; arg != args.end(); ++arg) {
-        deps.push_back(*arg);
-    }
-
-    // Key is striped module name to match names in alias file
-    std::size_t start = args[0].find_last_of('/');
-    std::size_t end = args[0].find(".ko:");
-    if ((end - start) <= 1) return Error() << "malformed dependency line";
-    auto mod_name = args[0].substr(start + 1, (end - start) - 1);
-    // module names can have '-', but their file names will have '_'
-    std::replace(mod_name.begin(), mod_name.end(), '-', '_');
-    this->module_deps_[mod_name] = deps;
-
-    return Success();
-}
-
-Result<Success> ModaliasHandler::ParseAliasCallback(std::vector<std::string>&& args) {
-    auto it = args.begin();
-    const std::string& type = *it++;
-
-    if (type != "alias") {
-        return Error() << "we only handle alias lines, got: " << type;
-    }
-
-    if (args.size() != 3) {
-        return Error() << "alias lines must have 3 entries";
-    }
-
-    std::string& alias = *it++;
-    std::string& module_name = *it++;
-    this->module_aliases_.emplace_back(alias, module_name);
-
-    return Success();
-}
-
-ModaliasHandler::ModaliasHandler() {
-    using namespace std::placeholders;
-
-    static const std::string base_paths[] = {
-            "/vendor/lib/modules/",
-            "/lib/modules/",
-            "/odm/lib/modules/",
-    };
-
-    Parser alias_parser;
-    auto alias_callback = std::bind(&ModaliasHandler::ParseAliasCallback, this, _1);
-    alias_parser.AddSingleLineParser("alias", alias_callback);
-    for (const auto& base_path : base_paths) alias_parser.ParseConfig(base_path + "modules.alias");
-
-    Parser dep_parser;
-    auto dep_callback = std::bind(&ModaliasHandler::ParseDepCallback, this, _1);
-    dep_parser.AddSingleLineParser("", dep_callback);
-    for (const auto& base_path : base_paths) dep_parser.ParseConfig(base_path + "modules.dep");
-}
-
-Result<Success> ModaliasHandler::Insmod(const std::string& path_name, const std::string& args) {
-    base::unique_fd fd(
-            TEMP_FAILURE_RETRY(open(path_name.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
-    if (fd == -1) return ErrnoError() << "Could not open module '" << path_name << "'";
-
-    int ret = syscall(__NR_finit_module, fd.get(), args.c_str(), 0);
-    if (ret != 0) {
-        if (errno == EEXIST) {
-            // Module already loaded
-            return Success();
-        }
-        return ErrnoError() << "Failed to insmod '" << path_name << "' with args '" << args << "'";
-    }
-
-    LOG(INFO) << "Loaded kernel module " << path_name;
-    return Success();
-}
-
-Result<Success> ModaliasHandler::InsmodWithDeps(const std::string& module_name,
-                                                const std::string& args) {
-    if (module_name.empty()) {
-        return Error() << "Need valid module name";
-    }
-
-    auto it = module_deps_.find(module_name);
-    if (it == module_deps_.end()) {
-        return Error() << "Module '" << module_name << "' not in dependency file";
-    }
-    auto& dependencies = it->second;
-
-    // load module dependencies in reverse order
-    for (auto dep = dependencies.rbegin(); dep != dependencies.rend() - 1; ++dep) {
-        if (auto result = Insmod(*dep, ""); !result) return result;
-    }
-
-    // load target module itself with args
-    return Insmod(dependencies[0], args);
-}
+ModaliasHandler::ModaliasHandler(const std::vector<std::string>& base_paths)
+    : modprobe_(base_paths) {}
 
 void ModaliasHandler::HandleUevent(const Uevent& uevent) {
     if (uevent.modalias.empty()) return;
-
-    for (const auto& [alias, module] : module_aliases_) {
-        if (fnmatch(alias.c_str(), uevent.modalias.c_str(), 0) != 0) continue;  // Keep looking
-
-        LOG(DEBUG) << "Loading kernel module '" << module << "' for alias '" << uevent.modalias
-                   << "'";
-
-        if (auto result = InsmodWithDeps(module, ""); !result) {
-            LOG(ERROR) << "Cannot load module: " << result.error();
-            // try another one since there may be another match
-            continue;
-        }
-
-        // loading was successful
-        return;
-    }
+    modprobe_.LoadWithAliases(uevent.modalias, true);
 }
 
 }  // namespace init
diff --git a/init/modalias_handler.h b/init/modalias_handler.h
index 3247c86..ce89a05 100644
--- a/init/modalias_handler.h
+++ b/init/modalias_handler.h
@@ -17,10 +17,10 @@
 #pragma once
 
 #include <string>
-#include <unordered_map>
 #include <vector>
 
-#include "result.h"
+#include <modprobe/modprobe.h>
+
 #include "uevent.h"
 #include "uevent_handler.h"
 
@@ -29,20 +29,13 @@
 
 class ModaliasHandler : public UeventHandler {
   public:
-    ModaliasHandler();
+    ModaliasHandler(const std::vector<std::string>&);
     virtual ~ModaliasHandler() = default;
 
     void HandleUevent(const Uevent& uevent) override;
 
   private:
-    Result<Success> InsmodWithDeps(const std::string& module_name, const std::string& args);
-    Result<Success> Insmod(const std::string& path_name, const std::string& args);
-
-    Result<Success> ParseDepCallback(std::vector<std::string>&& args);
-    Result<Success> ParseAliasCallback(std::vector<std::string>&& args);
-
-    std::vector<std::pair<std::string, std::string>> module_aliases_;
-    std::unordered_map<std::string, std::vector<std::string>> module_deps_;
+    Modprobe modprobe_;
 };
 
 }  // namespace init
diff --git a/init/mount_handler.cpp b/init/mount_handler.cpp
index c8f0e76..0e4e024 100644
--- a/init/mount_handler.cpp
+++ b/init/mount_handler.cpp
@@ -38,7 +38,6 @@
 #include <libdm/dm.h>
 
 #include "epoll.h"
-#include "property_service.h"
 
 namespace android {
 namespace init {
@@ -96,7 +95,7 @@
     // handling, except for clearing non-existent or already clear property.
     // Goal is reduction of empty properties and associated triggers.
     if (value.empty() && android::base::GetProperty(mount_prop, "").empty()) return;
-    property_set(mount_prop, value);
+    android::base::SetProperty(mount_prop, value);
 }
 
 }  // namespace
@@ -121,7 +120,7 @@
 }
 
 MountHandler::~MountHandler() {
-    if (fp_) epoll_->UnregisterHandler(fileno(fp_.get())).IgnoreError();
+    if (fp_) epoll_->UnregisterHandler(fileno(fp_.get()));
 }
 
 void MountHandler::MountHandlerFunction() {
@@ -140,11 +139,11 @@
         }
     }
     free(buf);
-    for (auto entry : untouched) {
+    for (auto& entry : untouched) {
         SetMountProperty(entry, false);
         mounts_.erase(entry);
     }
-    for (auto entry : touched) {
+    for (auto& entry : touched) {
         SetMountProperty(entry, true);
         mounts_.emplace(std::move(entry));
     }
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 5305dc7..93eb244 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -25,7 +25,9 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <android-base/result.h>
 #include <android-base/unique_fd.h>
+#include <apex_manifest.pb.h>
 
 #include "util.h"
 
@@ -79,6 +81,90 @@
     return updatable;
 }
 
+static Result<void> MountDir(const std::string& path, const std::string& mount_path) {
+    if (int ret = mkdir(mount_path.c_str(), 0755); ret != 0 && ret != EEXIST) {
+        return ErrnoError() << "Could not create mount point " << mount_path;
+    }
+    if (mount(path.c_str(), mount_path.c_str(), nullptr, MS_BIND, nullptr) != 0) {
+        return ErrnoError() << "Could not bind mount " << path << " to " << mount_path;
+    }
+    return {};
+}
+
+static Result<std::string> GetApexName(const std::string& apex_dir) {
+    const std::string manifest_path = apex_dir + "/apex_manifest.pb";
+    std::string content;
+    if (!android::base::ReadFileToString(manifest_path, &content)) {
+        return Error() << "Failed to read manifest file: " << manifest_path;
+    }
+    apex::proto::ApexManifest manifest;
+    if (!manifest.ParseFromString(content)) {
+        return Error() << "Can't parse manifest file: " << manifest_path;
+    }
+    return manifest.name();
+}
+
+static Result<void> ActivateFlattenedApexesFrom(const std::string& from_dir,
+                                                const std::string& to_dir) {
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(from_dir.c_str()), closedir);
+    if (!dir) {
+        return {};
+    }
+    dirent* entry;
+    while ((entry = readdir(dir.get())) != nullptr) {
+        if (entry->d_name[0] == '.') continue;
+        if (entry->d_type == DT_DIR) {
+            const std::string apex_path = from_dir + "/" + entry->d_name;
+            const auto apex_name = GetApexName(apex_path);
+            if (!apex_name) {
+                LOG(ERROR) << apex_path << " is not an APEX directory: " << apex_name.error();
+                continue;
+            }
+            const std::string mount_path = to_dir + "/" + (*apex_name);
+            if (auto result = MountDir(apex_path, mount_path); !result) {
+                return result;
+            }
+        }
+    }
+    return {};
+}
+
+static bool ActivateFlattenedApexesIfPossible() {
+    if (IsRecoveryMode() || IsApexUpdatable()) {
+        return true;
+    }
+
+    const std::string kApexTop = "/apex";
+    const std::vector<std::string> kBuiltinDirsForApexes = {
+            "/system/apex",
+            "/system_ext/apex",
+            "/product/apex",
+            "/vendor/apex",
+    };
+
+    for (const auto& dir : kBuiltinDirsForApexes) {
+        if (auto result = ActivateFlattenedApexesFrom(dir, kApexTop); !result) {
+            LOG(ERROR) << result.error();
+            return false;
+        }
+    }
+    return true;
+}
+
+static Result<void> MountLinkerConfigForDefaultNamespace() {
+    // No need to mount linkerconfig for default mount namespace if the path does not exist (which
+    // would mean it is already mounted)
+    if (access("/linkerconfig/default", 0) != 0) {
+        return {};
+    }
+
+    if (mount("/linkerconfig/default", "/linkerconfig", nullptr, MS_BIND | MS_REC, nullptr) != 0) {
+        return ErrnoError() << "Failed to mount linker configuration for default mount namespace.";
+    }
+
+    return {};
+}
+
 static android::base::unique_fd bootstrap_ns_fd;
 static android::base::unique_fd default_ns_fd;
 
@@ -100,6 +186,11 @@
     // the bootstrap namespace get APEXes from the read-only partition.
     if (!(MakePrivate("/apex"))) return false;
 
+    // /linkerconfig is a private mountpoint to give a different linker configuration
+    // based on the mount namespace. Subdirectory will be bind-mounted based on current mount
+    // namespace
+    if (!(MakePrivate("/linkerconfig"))) return false;
+
     bootstrap_ns_fd.reset(OpenMountNamespace());
     bootstrap_ns_id = GetMountNamespaceId();
 
@@ -129,6 +220,8 @@
         default_ns_id = GetMountNamespaceId();
     }
 
+    success &= ActivateFlattenedApexesIfPossible();
+
     LOG(INFO) << "SetupMountNamespaces done";
     return success;
 }
@@ -143,6 +236,11 @@
             PLOG(ERROR) << "Failed to switch back to the default mount namespace.";
             return false;
         }
+
+        if (auto result = MountLinkerConfigForDefaultNamespace(); !result) {
+            LOG(ERROR) << result.error();
+            return false;
+        }
     }
 
     LOG(INFO) << "Switched to default mount namespace";
diff --git a/init/parser.cpp b/init/parser.cpp
index bbfbdc6..6ab61cb 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -37,7 +37,7 @@
 }
 
 void Parser::AddSingleLineParser(const std::string& prefix, LineCallback callback) {
-    line_callbacks_.emplace_back(prefix, callback);
+    line_callbacks_.emplace_back(prefix, std::move(callback));
 }
 
 void Parser::ParseData(const std::string& filename, std::string* data) {
diff --git a/init/parser.h b/init/parser.h
index f30bda7..95b0cd7 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -27,7 +27,7 @@
 //  SectionParser is an interface that can parse a given 'section' in init.
 //
 //  You can implement up to 4 functions below, with ParseSection being mandatory. The first two
-//  functions return Result<Success> indicating if they have an error. It will be reported along
+//  functions return Result<void> indicating if they have an error. It will be reported along
 //  with the filename and line number of where the error occurred.
 //
 //  1) ParseSection
@@ -51,10 +51,10 @@
 class SectionParser {
   public:
     virtual ~SectionParser() {}
-    virtual Result<Success> ParseSection(std::vector<std::string>&& args,
-                                         const std::string& filename, int line) = 0;
-    virtual Result<Success> ParseLineSection(std::vector<std::string>&&, int) { return Success(); };
-    virtual Result<Success> EndSection() { return Success(); };
+    virtual Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
+                                      int line) = 0;
+    virtual Result<void> ParseLineSection(std::vector<std::string>&&, int) { return {}; };
+    virtual Result<void> EndSection() { return {}; };
     virtual void EndFile(){};
 };
 
@@ -67,7 +67,7 @@
     //  Similar to ParseSection() and ParseLineSection(), this function returns bool with false
     //  indicating a failure and has an std::string* err parameter into which an error string can
     //  be written.
-    using LineCallback = std::function<Result<Success>(std::vector<std::string>&&)>;
+    using LineCallback = std::function<Result<void>(std::vector<std::string>&&)>;
 
     Parser();
 
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 21adce9..1758cfa 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -31,10 +31,11 @@
 
 #include "util.h"
 
+using android::base::Dirname;
 using android::base::ReadFdToString;
 using android::base::StartsWith;
-using android::base::WriteStringToFd;
 using android::base::unique_fd;
+using android::base::WriteStringToFd;
 
 namespace android {
 namespace init {
@@ -69,7 +70,7 @@
             continue;
         }
 
-        unique_fd fd(openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW));
+        unique_fd fd(openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
         if (fd == -1) {
             PLOG(ERROR) << "Unable to open persistent property file \"" << entry->d_name << "\"";
             continue;
@@ -169,7 +170,7 @@
     return Error() << "Unable to parse persistent property file: Could not parse protobuf";
 }
 
-Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) {
+Result<void> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) {
     const std::string temp_filename = persistent_property_filename + ".tmp";
     unique_fd fd(TEMP_FAILURE_RETRY(
         open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
@@ -191,7 +192,19 @@
         unlink(temp_filename.c_str());
         return Error(saved_errno) << "Unable to rename persistent property file";
     }
-    return Success();
+
+    // rename() is atomic with regards to the kernel's filesystem buffers, but the parent
+    // directories must be fsync()'ed otherwise, the rename is not necessarily written to storage.
+    // Note in this case, that the source and destination directories are the same, so only one
+    // fsync() is required.
+    auto dir = Dirname(persistent_property_filename);
+    auto dir_fd = unique_fd{open(dir.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC)};
+    if (dir_fd < 0) {
+        return ErrnoError() << "Unable to open persistent properties directory for fsync()";
+    }
+    fsync(dir_fd);
+
+    return {};
 }
 
 // Persistent properties are not written often, so we rather not keep any data in memory and read
diff --git a/init/persistent_properties.h b/init/persistent_properties.h
index 5f4df85..3845a0d 100644
--- a/init/persistent_properties.h
+++ b/init/persistent_properties.h
@@ -30,7 +30,7 @@
 
 // Exposed only for testing
 Result<PersistentProperties> LoadPersistentPropertyFile();
-Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties);
+Result<void> WritePersistentPropertyFile(const PersistentProperties& persistent_properties);
 extern std::string persistent_property_filename;
 
 }  // namespace init
diff --git a/init/property_service.cpp b/init/property_service.cpp
index f2c7462..5b35ad2 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -41,7 +41,10 @@
 
 #include <map>
 #include <memory>
+#include <mutex>
+#include <optional>
 #include <queue>
+#include <thread>
 #include <vector>
 
 #include <android-base/chrono_utils.h>
@@ -61,8 +64,10 @@
 #include "init.h"
 #include "persistent_properties.h"
 #include "property_type.h"
+#include "proto_utils.h"
 #include "selinux.h"
 #include "subcontext.h"
+#include "system/core/init/property_service.pb.h"
 #include "util.h"
 
 using namespace std::literals;
@@ -74,6 +79,7 @@
 using android::base::StringPrintf;
 using android::base::Timer;
 using android::base::Trim;
+using android::base::unique_fd;
 using android::base::WriteStringToFile;
 using android::properties::BuildTrie;
 using android::properties::ParsePropertyInfoFile;
@@ -86,29 +92,27 @@
 static bool persistent_properties_loaded = false;
 
 static int property_set_fd = -1;
+static int init_socket = -1;
+static bool accept_messages = false;
 
 static PropertyInfoAreaFile property_info_area;
 
-uint32_t InitPropertySet(const std::string& name, const std::string& value);
-
-uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet;
-
-void CreateSerializedPropertyInfo();
-
 struct PropertyAuditData {
     const ucred* cr;
     const char* name;
 };
 
-void property_init() {
-    mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
-    CreateSerializedPropertyInfo();
-    if (__system_property_area_init()) {
-        LOG(FATAL) << "Failed to initialize property area";
+static int PropertyAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
+    auto* d = reinterpret_cast<PropertyAuditData*>(data);
+
+    if (!d || !d->name || !d->cr) {
+        LOG(ERROR) << "AuditCallback invoked with null data arguments!";
+        return 0;
     }
-    if (!property_info_area.LoadDefaultPath()) {
-        LOG(FATAL) << "Failed to load serialized property info file";
-    }
+
+    snprintf(buf, len, "property=%s pid=%d uid=%d gid=%d", d->name, d->cr->pid, d->cr->uid,
+             d->cr->gid);
+    return 0;
 }
 
 bool CanReadProperty(const std::string& source_context, const std::string& name) {
@@ -143,6 +147,17 @@
     return has_access;
 }
 
+static void SendPropertyChanged(const std::string& name, const std::string& value) {
+    auto property_msg = PropertyMessage{};
+    auto* changed_message = property_msg.mutable_changed_message();
+    changed_message->set_name(name);
+    changed_message->set_value(value);
+
+    if (auto result = SendMessage(init_socket, property_msg); !result) {
+        LOG(ERROR) << "Failed to send property changed message: " << result.error();
+    }
+}
+
 static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
     size_t valuelen = value.size();
 
@@ -151,13 +166,8 @@
         return PROP_ERROR_INVALID_NAME;
     }
 
-    if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
-        *error = "Property value too long";
-        return PROP_ERROR_INVALID_VALUE;
-    }
-
-    if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
-        *error = "Value is not a UTF8 encoded string";
+    if (auto result = IsLegalPropertyValue(name, value); !result) {
+        *error = result.error().message();
         return PROP_ERROR_INVALID_VALUE;
     }
 
@@ -183,112 +193,54 @@
     if (persistent_properties_loaded && StartsWith(name, "persist.")) {
         WritePersistentProperty(name, value);
     }
-    property_changed(name, value);
+    // If init hasn't started its main loop, then it won't be handling property changed messages
+    // anyway, so there's no need to try to send them.
+    if (accept_messages) {
+        SendPropertyChanged(name, value);
+    }
     return PROP_SUCCESS;
 }
 
-typedef int (*PropertyAsyncFunc)(const std::string&, const std::string&);
+class AsyncRestorecon {
+  public:
+    void TriggerRestorecon(const std::string& path) {
+        auto guard = std::lock_guard{mutex_};
+        paths_.emplace(path);
 
-struct PropertyChildInfo {
-    pid_t pid;
-    PropertyAsyncFunc func;
-    std::string name;
-    std::string value;
+        if (!thread_started_) {
+            thread_started_ = true;
+            std::thread{&AsyncRestorecon::ThreadFunction, this}.detach();
+        }
+    }
+
+  private:
+    void ThreadFunction() {
+        auto lock = std::unique_lock{mutex_};
+
+        while (!paths_.empty()) {
+            auto path = paths_.front();
+            paths_.pop();
+
+            lock.unlock();
+            if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
+                LOG(ERROR) << "Asynchronous restorecon of '" << path << "' failed'";
+            }
+            android::base::SetProperty(kRestoreconProperty, path);
+            lock.lock();
+        }
+
+        thread_started_ = false;
+    }
+
+    std::mutex mutex_;
+    std::queue<std::string> paths_;
+    bool thread_started_ = false;
 };
 
-static std::queue<PropertyChildInfo> property_children;
-
-static void PropertyChildLaunch() {
-    auto& info = property_children.front();
-    pid_t pid = fork();
-    if (pid < 0) {
-        LOG(ERROR) << "Failed to fork for property_set_async";
-        while (!property_children.empty()) {
-            property_children.pop();
-        }
-        return;
-    }
-    if (pid != 0) {
-        info.pid = pid;
-    } else {
-        if (info.func(info.name, info.value) != 0) {
-            LOG(ERROR) << "property_set_async(\"" << info.name << "\", \"" << info.value
-                       << "\") failed";
-        }
-        _exit(0);
-    }
-}
-
-bool PropertyChildReap(pid_t pid) {
-    if (property_children.empty()) {
-        return false;
-    }
-    auto& info = property_children.front();
-    if (info.pid != pid) {
-        return false;
-    }
-    std::string error;
-    if (PropertySet(info.name, info.value, &error) != PROP_SUCCESS) {
-        LOG(ERROR) << "Failed to set async property " << info.name << " to " << info.value << ": "
-                   << error;
-    }
-    property_children.pop();
-    if (!property_children.empty()) {
-        PropertyChildLaunch();
-    }
-    return true;
-}
-
-static uint32_t PropertySetAsync(const std::string& name, const std::string& value,
-                                 PropertyAsyncFunc func, std::string* error) {
-    if (value.empty()) {
-        return PropertySet(name, value, error);
-    }
-
-    PropertyChildInfo info;
-    info.func = func;
-    info.name = name;
-    info.value = value;
-    property_children.push(info);
-    if (property_children.size() == 1) {
-        PropertyChildLaunch();
-    }
-    return PROP_SUCCESS;
-}
-
-static int RestoreconRecursiveAsync(const std::string& name, const std::string& value) {
-    return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
-}
-
-uint32_t InitPropertySet(const std::string& name, const std::string& value) {
-    if (StartsWith(name, "ctl.")) {
-        LOG(ERROR) << "InitPropertySet: Do not set ctl. properties from init; call the Service "
-                      "functions directly";
-        return PROP_ERROR_INVALID_NAME;
-    }
-    if (name == "selinux.restorecon_recursive") {
-        LOG(ERROR) << "InitPropertySet: Do not set selinux.restorecon_recursive from init; use the "
-                      "restorecon builtin directly";
-        return PROP_ERROR_INVALID_NAME;
-    }
-
-    uint32_t result = 0;
-    ucred cr = {.pid = 1, .uid = 0, .gid = 0};
-    std::string error;
-    result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error);
-    if (result != PROP_SUCCESS) {
-        LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
-    }
-
-    return result;
-}
-
 class SocketConnection {
   public:
     SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {}
 
-    ~SocketConnection() { close(socket_); }
-
     bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) {
         return RecvFully(value, sizeof(*value), timeout_ms);
     }
@@ -325,22 +277,27 @@
     }
 
     bool SendUint32(uint32_t value) {
+        if (!socket_.ok()) {
+            return true;
+        }
         int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0));
         return result == sizeof(value);
     }
 
-    int socket() { return socket_; }
+    bool GetSourceContext(std::string* source_context) const {
+        char* c_source_context = nullptr;
+        if (getpeercon(socket_, &c_source_context) != 0) {
+            return false;
+        }
+        *source_context = c_source_context;
+        freecon(c_source_context);
+        return true;
+    }
+
+    [[nodiscard]] int Release() { return socket_.release(); }
 
     const ucred& cred() { return cred_; }
 
-    std::string source_context() const {
-        char* source_context = nullptr;
-        getpeercon(socket_, &source_context);
-        std::string result = source_context;
-        freecon(source_context);
-        return result;
-    }
-
   private:
     bool PollIn(uint32_t* timeout_ms) {
         struct pollfd ufds[1];
@@ -408,12 +365,46 @@
         return bytes_left == 0;
     }
 
-    int socket_;
+    unique_fd socket_;
     ucred cred_;
 
     DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection);
 };
 
+static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
+                                   SocketConnection* socket, std::string* error) {
+    if (!accept_messages) {
+        *error = "Received control message after shutdown, ignoring";
+        return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+    }
+
+    auto property_msg = PropertyMessage{};
+    auto* control_message = property_msg.mutable_control_message();
+    control_message->set_msg(msg);
+    control_message->set_name(name);
+    control_message->set_pid(pid);
+
+    // We must release the fd before sending it to init, otherwise there will be a race with init.
+    // If init calls close() before Release(), then fdsan will see the wrong tag and abort().
+    int fd = -1;
+    if (socket != nullptr && SelinuxGetVendorAndroidVersion() > __ANDROID_API_Q__) {
+        fd = socket->Release();
+        control_message->set_fd(fd);
+    }
+
+    if (auto result = SendMessage(init_socket, property_msg); !result) {
+        // We've already released the fd above, so if we fail to send the message to init, we need
+        // to manually free it here.
+        if (fd != -1) {
+            close(fd);
+        }
+        *error = "Failed to send control message: " + result.error().message();
+        return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
+    }
+
+    return PROP_SUCCESS;
+}
+
 bool CheckControlPropertyPerms(const std::string& name, const std::string& value,
                                const std::string& source_context, const ucred& cr) {
     // We check the legacy method first but these properties are dontaudit, so we only log an audit
@@ -470,7 +461,7 @@
         return PROP_ERROR_PERMISSION_DENIED;
     }
 
-    if (type == nullptr || !CheckType(type, value)) {
+    if (!CheckType(type, value)) {
         *error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
                               (type ?: "(null)"));
         return PROP_ERROR_INVALID_VALUE;
@@ -481,14 +472,14 @@
 
 // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
 uint32_t HandlePropertySet(const std::string& name, const std::string& value,
-                           const std::string& source_context, const ucred& cr, std::string* error) {
+                           const std::string& source_context, const ucred& cr,
+                           SocketConnection* socket, std::string* error) {
     if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) {
         return ret;
     }
 
     if (StartsWith(name, "ctl.")) {
-        HandleControlMessage(name.c_str() + 4, value, cr.pid);
-        return PROP_SUCCESS;
+        return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error);
     }
 
     // sys.powerctl is a special property that is used to make the device reboot.  We want to log
@@ -506,8 +497,14 @@
                   << process_log_string;
     }
 
-    if (name == "selinux.restorecon_recursive") {
-        return PropertySetAsync(name, value, RestoreconRecursiveAsync, error);
+    // If a process other than init is writing a non-empty value, it means that process is
+    // requesting that init performs a restorecon operation on the path specified by 'value'.
+    // We use a thread to do this restorecon operation to prevent holding up init, as it may take
+    // a long time to complete.
+    if (name == kRestoreconProperty && cr.pid != 1 && !value.empty()) {
+        static AsyncRestorecon async_restorecon;
+        async_restorecon.TriggerRestorecon(value);
+        return PROP_SUCCESS;
     }
 
     return PropertySet(name, value, error);
@@ -553,14 +550,19 @@
         prop_name[PROP_NAME_MAX-1] = 0;
         prop_value[PROP_VALUE_MAX-1] = 0;
 
+        std::string source_context;
+        if (!socket.GetSourceContext(&source_context)) {
+            PLOG(ERROR) << "Unable to set property '" << prop_name << "': getpeercon() failed";
+            return;
+        }
+
         const auto& cr = socket.cred();
         std::string error;
         uint32_t result =
-            HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
+                HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error);
         if (result != PROP_SUCCESS) {
-            LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
-                       << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
-                       << error;
+            LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid
+                       << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
         }
 
         break;
@@ -576,13 +578,19 @@
           return;
         }
 
+        std::string source_context;
+        if (!socket.GetSourceContext(&source_context)) {
+            PLOG(ERROR) << "Unable to set property '" << name << "': getpeercon() failed";
+            socket.SendUint32(PROP_ERROR_PERMISSION_DENIED);
+            return;
+        }
+
         const auto& cr = socket.cred();
         std::string error;
-        uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
+        uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error);
         if (result != PROP_SUCCESS) {
-            LOG(ERROR) << "Unable to set property '" << name << "' to '" << value
-                       << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
-                       << error;
+            LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid
+                       << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
         }
         socket.SendUint32(result);
         break;
@@ -595,6 +603,18 @@
     }
 }
 
+uint32_t InitPropertySet(const std::string& name, const std::string& value) {
+    uint32_t result = 0;
+    ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+    std::string error;
+    result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
+    if (result != PROP_SUCCESS) {
+        LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
+    }
+
+    return result;
+}
+
 static bool load_properties_from_file(const char*, const char*,
                                       std::map<std::string, std::string>*);
 
@@ -607,11 +627,16 @@
     char *key, *value, *eol, *sol, *tmp, *fn;
     size_t flen = 0;
 
-    const char* context = kInitContext.c_str();
+    static constexpr const char* const kVendorPathPrefixes[2] = {
+            "/vendor",
+            "/odm",
+    };
+
+    const char* context = kInitContext;
     if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
-        for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
-            if (StartsWith(filename, path_prefix)) {
-                context = secontext;
+        for (const auto& vendor_path_prefix : kVendorPathPrefixes) {
+            if (StartsWith(filename, vendor_path_prefix)) {
+                context = kVendorContext;
             }
         }
     }
@@ -643,13 +668,14 @@
             }
 
             std::string raw_filename(fn);
-            std::string expanded_filename;
-            if (!expand_props(raw_filename, &expanded_filename)) {
-                LOG(ERROR) << "Could not expand filename '" << raw_filename << "'";
+            auto expanded_filename = ExpandProps(raw_filename);
+
+            if (!expanded_filename) {
+                LOG(ERROR) << "Could not expand filename ': " << expanded_filename.error();
                 continue;
             }
 
-            load_properties_from_file(expanded_filename.c_str(), key, properties);
+            load_properties_from_file(expanded_filename->c_str(), key, properties);
         } else {
             value = strchr(key, '=');
             if (!value) continue;
@@ -662,14 +688,14 @@
 
             if (flen > 0) {
                 if (filter[flen - 1] == '*') {
-                    if (strncmp(key, filter, flen - 1)) continue;
+                    if (strncmp(key, filter, flen - 1) != 0) continue;
                 } else {
-                    if (strcmp(key, filter)) continue;
+                    if (strcmp(key, filter) != 0) continue;
                 }
             }
 
             if (StartsWith(key, "ctl.") || key == "sys.powerctl"s ||
-                key == "selinux.restorecon_recursive"s) {
+                std::string{key} == kRestoreconProperty) {
                 LOG(ERROR) << "Ignoring disallowed property '" << key
                            << "' with special meaning in prop file '" << filename << "'";
                 continue;
@@ -720,11 +746,11 @@
     bool is_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
     std::string config = android::base::GetProperty("persist.sys.usb.config", "");
     if (config.empty()) {
-        property_set("persist.sys.usb.config", is_debuggable ? "adb" : "none");
+        InitPropertySet("persist.sys.usb.config", is_debuggable ? "adb" : "none");
     } else if (is_debuggable && config.find("adb") == std::string::npos &&
                config.length() + 4 < PROP_VALUE_MAX) {
         config.append(",adb");
-        property_set("persist.sys.usb.config", config);
+        InitPropertySet("persist.sys.usb.config", config);
     }
 }
 
@@ -742,33 +768,6 @@
     }
 }
 
-/* When booting an encrypted system, /data is not mounted when the
- * property service is started, so any properties stored there are
- * not loaded.  Vold triggers init to load these properties once it
- * has mounted /data.
- */
-void load_persist_props(void) {
-    // Devices with FDE have load_persist_props called twice; the first time when the temporary
-    // /data partition is mounted and then again once /data is truly mounted.  We do not want to
-    // read persistent properties from the temporary /data partition or mark persistent properties
-    // as having been loaded during the first call, so we return in that case.
-    std::string crypto_state = android::base::GetProperty("ro.crypto.state", "");
-    std::string crypto_type = android::base::GetProperty("ro.crypto.type", "");
-    if (crypto_state == "encrypted" && crypto_type == "block") {
-        static size_t num_calls = 0;
-        if (++num_calls == 1) return;
-    }
-
-    load_override_properties();
-    /* Read persistent properties after all default values have been loaded. */
-    auto persistent_properties = LoadPersistentProperties();
-    for (const auto& persistent_property_record : persistent_properties.properties()) {
-        property_set(persistent_property_record.name(), persistent_property_record.value());
-    }
-    persistent_properties_loaded = true;
-    property_set("ro.persistent_properties.ready", "true");
-}
-
 // If the ro.product.[brand|device|manufacturer|model|name] properties have not been explicitly
 // set, derive them from ro.product.${partition}.* properties
 static void property_initialize_ro_product_props() {
@@ -777,10 +776,9 @@
             "brand", "device", "manufacturer", "model", "name",
     };
     const char* RO_PRODUCT_PROPS_ALLOWED_SOURCES[] = {
-            "odm", "product", "product_services", "system", "vendor",
+            "odm", "product", "system_ext", "system", "vendor",
     };
-    const char* RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER =
-            "product,product_services,odm,vendor,system";
+    const char* RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER = "product,odm,vendor,system_ext,system";
     const std::string EMPTY = "";
 
     std::string ro_product_props_source_order =
@@ -873,7 +871,7 @@
     }
 }
 
-void property_load_boot_defaults(bool load_debug_prop) {
+void PropertyLoadBootDefaults() {
     // TODO(b/117892318): merge prop.default and build.prop files into one
     // We read the properties and their values into a map, in order to always allow properties
     // loaded in the later property files to override the properties in loaded in the earlier
@@ -887,6 +885,7 @@
         }
     }
     load_properties_from_file("/system/build.prop", nullptr, &properties);
+    load_properties_from_file("/system_ext/build.prop", nullptr, &properties);
     load_properties_from_file("/vendor/default.prop", nullptr, &properties);
     load_properties_from_file("/vendor/build.prop", nullptr, &properties);
     if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_Q__) {
@@ -896,10 +895,9 @@
         load_properties_from_file("/odm/build.prop", nullptr, &properties);
     }
     load_properties_from_file("/product/build.prop", nullptr, &properties);
-    load_properties_from_file("/product_services/build.prop", nullptr, &properties);
     load_properties_from_file("/factory/factory.prop", "ro.*", &properties);
 
-    if (load_debug_prop) {
+    if (access(kDebugRamdiskProp, R_OK) == 0) {
         LOG(INFO) << "Loading " << kDebugRamdiskProp;
         load_properties_from_file(kDebugRamdiskProp, nullptr, &properties);
     }
@@ -918,19 +916,6 @@
     update_sys_usb_config();
 }
 
-static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
-    auto* d = reinterpret_cast<PropertyAuditData*>(data);
-
-    if (!d || !d->name || !d->cr) {
-        LOG(ERROR) << "AuditCallback invoked with null data arguments!";
-        return 0;
-    }
-
-    snprintf(buf, len, "property=%s pid=%d uid=%d gid=%d", d->name, d->cr->pid, d->cr->uid,
-             d->cr->gid);
-    return 0;
-}
-
 bool LoadPropertyInfoFromFile(const std::string& filename,
                               std::vector<PropertyInfoEntry>* property_infos) {
     auto file_contents = std::string();
@@ -940,7 +925,8 @@
     }
 
     auto errors = std::vector<std::string>{};
-    ParsePropertyInfoFile(file_contents, property_infos, &errors);
+    bool require_prefix_or_exact = SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__;
+    ParsePropertyInfoFile(file_contents, require_prefix_or_exact, property_infos, &errors);
     // Individual parsing errors are reported but do not cause a failed boot, which is what
     // returning false would do here.
     for (const auto& error : errors) {
@@ -960,6 +946,10 @@
         // Don't check for failure here, so we always have a sane list of properties.
         // E.g. In case of recovery, the vendor partition will not have mounted and we
         // still need the system / platform properties to function.
+        if (access("/system_ext/etc/selinux/system_ext_property_contexts", R_OK) != -1) {
+            LoadPropertyInfoFromFile("/system_ext/etc/selinux/system_ext_property_contexts",
+                                     &property_infos);
+        }
         if (!LoadPropertyInfoFromFile("/vendor/etc/selinux/vendor_property_contexts",
                                       &property_infos)) {
             // Fallback to nonplat_* if vendor_* doesn't exist.
@@ -977,6 +967,7 @@
         if (!LoadPropertyInfoFromFile("/plat_property_contexts", &property_infos)) {
             return;
         }
+        LoadPropertyInfoFromFile("/system_ext_property_contexts", &property_infos);
         if (!LoadPropertyInfoFromFile("/vendor_property_contexts", &property_infos)) {
             // Fallback to nonplat_* if vendor_* doesn't exist.
             LoadPropertyInfoFromFile("/nonplat_property_contexts", &property_infos);
@@ -1000,24 +991,183 @@
     selinux_android_restorecon(kPropertyInfosPath, 0);
 }
 
-void StartPropertyService(Epoll* epoll) {
+static void ExportKernelBootProps() {
+    constexpr const char* UNSET = "";
+    struct {
+        const char* src_prop;
+        const char* dst_prop;
+        const char* default_value;
+    } prop_map[] = {
+            // clang-format off
+        { "ro.boot.serialno",   "ro.serialno",   UNSET, },
+        { "ro.boot.mode",       "ro.bootmode",   "unknown", },
+        { "ro.boot.baseband",   "ro.baseband",   "unknown", },
+        { "ro.boot.bootloader", "ro.bootloader", "unknown", },
+        { "ro.boot.hardware",   "ro.hardware",   "unknown", },
+        { "ro.boot.revision",   "ro.revision",   "0", },
+            // clang-format on
+    };
+    for (const auto& prop : prop_map) {
+        std::string value = GetProperty(prop.src_prop, prop.default_value);
+        if (value != UNSET) InitPropertySet(prop.dst_prop, value);
+    }
+}
+
+static void ProcessKernelDt() {
+    if (!is_android_dt_value_expected("compatible", "android,firmware")) {
+        return;
+    }
+
+    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(get_android_dt_dir().c_str()), closedir);
+    if (!dir) return;
+
+    std::string dt_file;
+    struct dirent* dp;
+    while ((dp = readdir(dir.get())) != NULL) {
+        if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") ||
+            !strcmp(dp->d_name, "name")) {
+            continue;
+        }
+
+        std::string file_name = get_android_dt_dir() + dp->d_name;
+
+        android::base::ReadFileToString(file_name, &dt_file);
+        std::replace(dt_file.begin(), dt_file.end(), ',', '.');
+
+        InitPropertySet("ro.boot."s + dp->d_name, dt_file);
+    }
+}
+
+static void ProcessKernelCmdline() {
+    bool for_emulator = false;
+    ImportKernelCmdline([&](const std::string& key, const std::string& value) {
+        if (key == "qemu") {
+            for_emulator = true;
+        } else if (StartsWith(key, "androidboot.")) {
+            InitPropertySet("ro.boot." + key.substr(12), value);
+        }
+    });
+
+    if (for_emulator) {
+        ImportKernelCmdline([&](const std::string& key, const std::string& value) {
+            // In the emulator, export any kernel option with the "ro.kernel." prefix.
+            InitPropertySet("ro.kernel." + key, value);
+        });
+    }
+}
+
+void PropertyInit() {
     selinux_callback cb;
-    cb.func_audit = SelinuxAuditCallback;
+    cb.func_audit = PropertyAuditCallback;
     selinux_set_callback(SELINUX_CB_AUDIT, cb);
 
-    property_set("ro.property_service.version", "2");
+    mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
+    CreateSerializedPropertyInfo();
+    if (__system_property_area_init()) {
+        LOG(FATAL) << "Failed to initialize property area";
+    }
+    if (!property_info_area.LoadDefaultPath()) {
+        LOG(FATAL) << "Failed to load serialized property info file";
+    }
 
-    property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                                   false, 0666, 0, 0, nullptr);
-    if (property_set_fd == -1) {
-        PLOG(FATAL) << "start_property_service socket creation failed";
+    // If arguments are passed both on the command line and in DT,
+    // properties set in DT always have priority over the command-line ones.
+    ProcessKernelDt();
+    ProcessKernelCmdline();
+
+    // Propagate the kernel variables to internal variables
+    // used by init as well as the current required properties.
+    ExportKernelBootProps();
+
+    PropertyLoadBootDefaults();
+}
+
+static void HandleInitSocket() {
+    auto message = ReadMessage(init_socket);
+    if (!message) {
+        LOG(ERROR) << "Could not read message from init_dedicated_recv_socket: " << message.error();
+        return;
+    }
+
+    auto init_message = InitMessage{};
+    if (!init_message.ParseFromString(*message)) {
+        LOG(ERROR) << "Could not parse message from init";
+        return;
+    }
+
+    switch (init_message.msg_case()) {
+        case InitMessage::kLoadPersistentProperties: {
+            load_override_properties();
+            // Read persistent properties after all default values have been loaded.
+            auto persistent_properties = LoadPersistentProperties();
+            for (const auto& persistent_property_record : persistent_properties.properties()) {
+                InitPropertySet(persistent_property_record.name(),
+                                persistent_property_record.value());
+            }
+            InitPropertySet("ro.persistent_properties.ready", "true");
+            persistent_properties_loaded = true;
+            break;
+        }
+        case InitMessage::kStopSendingMessages: {
+            accept_messages = false;
+            break;
+        }
+        case InitMessage::kStartSendingMessages: {
+            accept_messages = true;
+            break;
+        }
+        default:
+            LOG(ERROR) << "Unknown message type from init: " << init_message.msg_case();
+    }
+}
+
+static void PropertyServiceThread() {
+    Epoll epoll;
+    if (auto result = epoll.Open(); !result) {
+        LOG(FATAL) << result.error();
+    }
+
+    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
+        LOG(FATAL) << result.error();
+    }
+
+    if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result) {
+        LOG(FATAL) << result.error();
+    }
+
+    while (true) {
+        auto pending_functions = epoll.Wait(std::nullopt);
+        if (!pending_functions) {
+            LOG(ERROR) << pending_functions.error();
+        } else {
+            for (const auto& function : *pending_functions) {
+                (*function)();
+            }
+        }
+    }
+}
+
+void StartPropertyService(int* epoll_socket) {
+    InitPropertySet("ro.property_service.version", "2");
+
+    int sockets[2];
+    if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
+        PLOG(FATAL) << "Failed to socketpair() between property_service and init";
+    }
+    *epoll_socket = sockets[0];
+    init_socket = sockets[1];
+    accept_messages = true;
+
+    if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
+                                   false, 0666, 0, 0, {})) {
+        property_set_fd = *result;
+    } else {
+        LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
     }
 
     listen(property_set_fd, 8);
 
-    if (auto result = epoll->RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
-        PLOG(FATAL) << result.error();
-    }
+    std::thread{PropertyServiceThread}.detach();
 }
 
 }  // namespace init
diff --git a/init/property_service.h b/init/property_service.h
index 85e7bc0..506d116 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_PROPERTY_H
-#define _INIT_PROPERTY_H
+#pragma once
 
 #include <sys/socket.h>
 
@@ -26,22 +25,12 @@
 namespace android {
 namespace init {
 
+static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";
+
 bool CanReadProperty(const std::string& source_context, const std::string& name);
 
-extern uint32_t (*property_set)(const std::string& name, const std::string& value);
-
-uint32_t HandlePropertySet(const std::string& name, const std::string& value,
-                           const std::string& source_context, const ucred& cr, std::string* error);
-
-extern bool PropertyChildReap(pid_t pid);
-
-void property_init(void);
-void property_load_boot_defaults(bool);
-void load_persist_props(void);
-void load_system_props(void);
-void StartPropertyService(Epoll* epoll);
+void PropertyInit();
+void StartPropertyService(int* epoll_socket);
 
 }  // namespace init
 }  // namespace android
-
-#endif  /* _INIT_PROPERTY_H */
diff --git a/init/property_service.proto b/init/property_service.proto
new file mode 100644
index 0000000..08268d9
--- /dev/null
+++ b/init/property_service.proto
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+message PropertyMessage {
+    message ControlMessage {
+        optional string msg = 1;
+        optional string name = 2;
+        optional int32 pid = 3;
+        optional int32 fd = 4;
+    }
+
+    message ChangedMessage {
+        optional string name = 1;
+        optional string value = 2;
+    }
+
+    oneof msg {
+        ControlMessage control_message = 1;
+        ChangedMessage changed_message = 2;
+    };
+}
+
+message InitMessage {
+    oneof msg {
+        bool load_persistent_properties = 1;
+        bool stop_sending_messages = 2;
+        bool start_sending_messages = 3;
+    };
+}
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index c038aff..0f4cd0d 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -56,6 +56,11 @@
 }
 
 TEST(property_service, non_utf8_value) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Skipping test, must be run as root.";
+        return;
+    }
+
     ASSERT_TRUE(SetProperty("property_service_utf8_test", "base_success"));
     EXPECT_FALSE(SetProperty("property_service_utf8_test", "\x80"));
     EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xC2\x01"));
diff --git a/init/proto_utils.h b/init/proto_utils.h
new file mode 100644
index 0000000..93a7d57
--- /dev/null
+++ b/init/proto_utils.h
@@ -0,0 +1,62 @@
+/*
+ * 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/socket.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "result.h"
+
+namespace android {
+namespace init {
+
+constexpr size_t kBufferSize = 4096;
+
+inline Result<std::string> ReadMessage(int socket) {
+    char buffer[kBufferSize] = {};
+    auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0));
+    if (result == 0) {
+        return Error();
+    } else if (result < 0) {
+        return ErrnoError();
+    }
+    return std::string(buffer, result);
+}
+
+template <typename T>
+Result<void> SendMessage(int socket, const T& message) {
+    std::string message_string;
+    if (!message.SerializeToString(&message_string)) {
+        return Error() << "Unable to serialize message";
+    }
+
+    if (message_string.size() > kBufferSize) {
+        return Error() << "Serialized message too long to send";
+    }
+
+    if (auto result =
+                TEMP_FAILURE_RETRY(send(socket, message_string.c_str(), message_string.size(), 0));
+        result != static_cast<long>(message_string.size())) {
+        return ErrnoError() << "send() failed to send message contents";
+    }
+    return {};
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 5b90969..225bc9c 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -19,28 +19,32 @@
 #include <dirent.h>
 #include <fcntl.h>
 #include <linux/fs.h>
-#include <mntent.h>
 #include <linux/loop.h>
+#include <mntent.h>
+#include <semaphore.h>
+#include <stdlib.h>
 #include <sys/cdefs.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
-#include <sys/swap.h>
 #include <sys/stat.h>
+#include <sys/swap.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include <chrono>
 #include <memory>
 #include <set>
 #include <thread>
 #include <vector>
 
+#include <InitProperties.sysprop.h>
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
-#include <android-base/stringprintf.h>
+#include <android-base/scopeguard.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <bootloader_message/bootloader_message.h>
@@ -50,22 +54,48 @@
 #include <private/android_filesystem_config.h>
 #include <selinux/selinux.h>
 
+#include "action.h"
 #include "action_manager.h"
+#include "builtin_arguments.h"
 #include "init.h"
-#include "property_service.h"
+#include "mount_namespace.h"
 #include "reboot_utils.h"
 #include "service.h"
+#include "service_list.h"
 #include "sigchld_handler.h"
+#include "util.h"
 
+#define PROC_SYSRQ "/proc/sysrq-trigger"
+
+using namespace std::literals;
+
+using android::base::boot_clock;
 using android::base::GetBoolProperty;
+using android::base::SetProperty;
 using android::base::Split;
-using android::base::StringPrintf;
 using android::base::Timer;
 using android::base::unique_fd;
+using android::base::WaitForProperty;
+using android::base::WriteStringToFile;
 
 namespace android {
 namespace init {
 
+static bool shutting_down = false;
+
+static const std::set<std::string> kDebuggingServices{"tombstoned", "logd", "adbd", "console"};
+
+static std::vector<Service*> GetDebuggingServices(bool only_post_data) {
+    std::vector<Service*> ret;
+    ret.reserve(kDebuggingServices.size());
+    for (const auto& s : ServiceList::GetInstance()) {
+        if (kDebuggingServices.count(s->name()) && (!only_post_data || s->is_post_data())) {
+            ret.push_back(s.get());
+        }
+    }
+    return ret;
+}
+
 // represents umount status during reboot / shutdown.
 enum UmountStat {
     /* umount succeeded. */
@@ -111,16 +141,16 @@
                     "-a",
                     mnt_fsname_.c_str(),
             };
-            android_fork_execvp_ext(arraysize(f2fs_argv), (char**)f2fs_argv, &st, true, LOG_KLOG,
-                                    true, nullptr, nullptr, 0);
+            logwrap_fork_execvp(arraysize(f2fs_argv), f2fs_argv, &st, false, LOG_KLOG, true,
+                                nullptr);
         } else if (IsExt4()) {
             const char* ext4_argv[] = {
                     "/system/bin/e2fsck",
                     "-y",
                     mnt_fsname_.c_str(),
             };
-            android_fork_execvp_ext(arraysize(ext4_argv), (char**)ext4_argv, &st, true, LOG_KLOG,
-                                    true, nullptr, nullptr, 0);
+            logwrap_fork_execvp(arraysize(ext4_argv), ext4_argv, &st, false, LOG_KLOG, true,
+                                nullptr);
         }
     }
 
@@ -155,11 +185,17 @@
     }
 }
 
-static void ShutdownVold() {
-    const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"};
+static Result<void> CallVdc(const std::string& system, const std::string& cmd) {
+    const char* vdc_argv[] = {"/system/bin/vdc", system.c_str(), cmd.c_str()};
     int status;
-    android_fork_execvp_ext(arraysize(vdc_argv), (char**)vdc_argv, &status, true, LOG_KLOG, true,
-                            nullptr, nullptr, 0);
+    if (logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG, true,
+                            nullptr) != 0) {
+        return ErrnoError() << "Failed to call '/system/bin/vdc " << system << " " << cmd << "'";
+    }
+    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+        return {};
+    }
+    return Error() << "'/system/bin/vdc " << system << " " << cmd << "' failed : " << status;
 }
 
 static void LogShutdownTime(UmountStat stat, Timer* t) {
@@ -167,11 +203,25 @@
                  << stat;
 }
 
-/* Find all read+write block devices and emulated devices in /proc/mounts
- * and add them to correpsponding list.
- */
-static bool FindPartitionsToUmount(std::vector<MountEntry>* blockDevPartitions,
-                                   std::vector<MountEntry>* emulatedPartitions, bool dump) {
+static bool IsDataMounted() {
+    std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent);
+    if (fp == nullptr) {
+        PLOG(ERROR) << "Failed to open /proc/mounts";
+        return false;
+    }
+    mntent* mentry;
+    while ((mentry = getmntent(fp.get())) != nullptr) {
+        if (mentry->mnt_dir == "/data"s) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// Find all read+write block devices and emulated devices in /proc/mounts and add them to
+// the correpsponding list.
+static bool FindPartitionsToUmount(std::vector<MountEntry>* block_dev_partitions,
+                                   std::vector<MountEntry>* emulated_partitions, bool dump) {
     std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent);
     if (fp == nullptr) {
         PLOG(ERROR) << "Failed to open /proc/mounts";
@@ -188,10 +238,10 @@
             // Do not umount them as shutdown critical services may rely on them.
             if (mount_dir != "/" && mount_dir != "/system" && mount_dir != "/vendor" &&
                 mount_dir != "/oem") {
-                blockDevPartitions->emplace(blockDevPartitions->begin(), *mentry);
+                block_dev_partitions->emplace(block_dev_partitions->begin(), *mentry);
             }
         } else if (MountEntry::IsEmulatedDevice(*mentry)) {
-            emulatedPartitions->emplace(emulatedPartitions->begin(), *mentry);
+            emulated_partitions->emplace(emulated_partitions->begin(), *mentry);
         }
     }
     return true;
@@ -202,13 +252,13 @@
     if (!security_getenforce()) {
         LOG(INFO) << "Run lsof";
         const char* lsof_argv[] = {"/system/bin/lsof"};
-        android_fork_execvp_ext(arraysize(lsof_argv), (char**)lsof_argv, &status, true, LOG_KLOG,
-                                true, nullptr, nullptr, 0);
+        logwrap_fork_execvp(arraysize(lsof_argv), lsof_argv, &status, false, LOG_KLOG, true,
+                            nullptr);
     }
     FindPartitionsToUmount(nullptr, nullptr, true);
     // dump current CPU stack traces and uninterruptible tasks
-    android::base::WriteStringToFile("l", "/proc/sysrq-trigger");
-    android::base::WriteStringToFile("w", "/proc/sysrq-trigger");
+    WriteStringToFile("l", PROC_SYSRQ);
+    WriteStringToFile("w", PROC_SYSRQ);
 }
 
 static UmountStat UmountPartitions(std::chrono::milliseconds timeout) {
@@ -248,7 +298,95 @@
     }
 }
 
-static void KillAllProcesses() { android::base::WriteStringToFile("i", "/proc/sysrq-trigger"); }
+static void KillAllProcesses() {
+    WriteStringToFile("i", PROC_SYSRQ);
+}
+
+// Create reboot/shutdwon monitor thread
+void RebootMonitorThread(unsigned int cmd, const std::string& reboot_target,
+                         sem_t* reboot_semaphore, std::chrono::milliseconds shutdown_timeout,
+                         bool* reboot_monitor_run) {
+    unsigned int remaining_shutdown_time = 0;
+
+    // 30 seconds more than the timeout passed to the thread as there is a final Umount pass
+    // after the timeout is reached.
+    constexpr unsigned int shutdown_watchdog_timeout_default = 30;
+    auto shutdown_watchdog_timeout = android::base::GetUintProperty(
+            "ro.build.shutdown.watchdog.timeout", shutdown_watchdog_timeout_default);
+    remaining_shutdown_time = shutdown_watchdog_timeout + shutdown_timeout.count() / 1000;
+
+    while (*reboot_monitor_run == true) {
+        if (TEMP_FAILURE_RETRY(sem_wait(reboot_semaphore)) == -1) {
+            LOG(ERROR) << "sem_wait failed and exit RebootMonitorThread()";
+            return;
+        }
+
+        timespec shutdown_timeout_timespec;
+        if (clock_gettime(CLOCK_MONOTONIC, &shutdown_timeout_timespec) == -1) {
+            LOG(ERROR) << "clock_gettime() fail! exit RebootMonitorThread()";
+            return;
+        }
+
+        // If there are some remaining shutdown time left from previous round, we use
+        // remaining time here.
+        shutdown_timeout_timespec.tv_sec += remaining_shutdown_time;
+
+        LOG(INFO) << "shutdown_timeout_timespec.tv_sec: " << shutdown_timeout_timespec.tv_sec;
+
+        int sem_return = 0;
+        while ((sem_return = sem_timedwait_monotonic_np(reboot_semaphore,
+                                                        &shutdown_timeout_timespec)) == -1 &&
+               errno == EINTR) {
+        }
+
+        if (sem_return == -1) {
+            LOG(ERROR) << "Reboot thread timed out";
+
+            if (android::base::GetBoolProperty("ro.debuggable", false) == true) {
+                if (false) {
+                    // SEPolicy will block debuggerd from running and this is intentional.
+                    // But these lines are left to be enabled during debugging.
+                    LOG(INFO) << "Try to dump init process call trace:";
+                    const char* vdc_argv[] = {"/system/bin/debuggerd", "-b", "1"};
+                    int status;
+                    logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG,
+                                        true, nullptr);
+                }
+                LOG(INFO) << "Show stack for all active CPU:";
+                WriteStringToFile("l", PROC_SYSRQ);
+
+                LOG(INFO) << "Show tasks that are in disk sleep(uninterruptable sleep), which are "
+                             "like "
+                             "blocked in mutex or hardware register access:";
+                WriteStringToFile("w", PROC_SYSRQ);
+            }
+
+            // In shutdown case,notify kernel to sync and umount fs to read-only before shutdown.
+            if (cmd == ANDROID_RB_POWEROFF || cmd == ANDROID_RB_THERMOFF) {
+                WriteStringToFile("s", PROC_SYSRQ);
+
+                WriteStringToFile("u", PROC_SYSRQ);
+
+                RebootSystem(cmd, reboot_target);
+            }
+
+            LOG(ERROR) << "Trigger crash at last!";
+            WriteStringToFile("c", PROC_SYSRQ);
+        } else {
+            timespec current_time_timespec;
+
+            if (clock_gettime(CLOCK_MONOTONIC, &current_time_timespec) == -1) {
+                LOG(ERROR) << "clock_gettime() fail! exit RebootMonitorThread()";
+                return;
+            }
+
+            remaining_shutdown_time =
+                    shutdown_timeout_timespec.tv_sec - current_time_timespec.tv_sec;
+
+            LOG(INFO) << "remaining_shutdown_time: " << remaining_shutdown_time;
+        }
+    }
+}
 
 /* Try umounting all emulated file systems R/W block device cfile systems.
  * This will just try umount and give it up if it fails.
@@ -259,12 +397,13 @@
  *
  * return true when umount was successful. false when timed out.
  */
-static UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeout) {
+static UmountStat TryUmountAndFsck(unsigned int cmd, bool run_fsck,
+                                   std::chrono::milliseconds timeout, sem_t* reboot_semaphore) {
     Timer t;
     std::vector<MountEntry> block_devices;
     std::vector<MountEntry> emulated_devices;
 
-    if (runFsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) {
+    if (run_fsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) {
         return UMOUNT_STAT_ERROR;
     }
 
@@ -278,12 +417,18 @@
         if ((st != UMOUNT_STAT_SUCCESS) && DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
     }
 
-    if (stat == UMOUNT_STAT_SUCCESS && runFsck) {
+    if (stat == UMOUNT_STAT_SUCCESS && run_fsck) {
+        LOG(INFO) << "Pause reboot monitor thread before fsck";
+        sem_post(reboot_semaphore);
+
         // fsck part is excluded from timeout check. It only runs for user initiated shutdown
         // and should not affect reboot time.
         for (auto& entry : block_devices) {
             entry.DoFsck();
         }
+
+        LOG(INFO) << "Resume reboot monitor thread after fsck";
+        sem_post(reboot_semaphore);
     }
     return stat;
 }
@@ -293,11 +438,11 @@
 #define ZRAM_DEVICE   "/dev/block/zram0"
 #define ZRAM_RESET    "/sys/block/zram0/reset"
 #define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
-static void KillZramBackingDevice() {
+static Result<void> KillZramBackingDevice() {
     std::string backing_dev;
-    if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return;
+    if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return {};
 
-    if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return;
+    if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return {};
 
     // cut the last "\n"
     backing_dev.erase(backing_dev.length() - 1);
@@ -306,41 +451,92 @@
     Timer swap_timer;
     LOG(INFO) << "swapoff() start...";
     if (swapoff(ZRAM_DEVICE) == -1) {
-        LOG(ERROR) << "zram_backing_dev: swapoff (" << backing_dev << ")" << " failed";
-        return;
+        return ErrnoError() << "zram_backing_dev: swapoff (" << backing_dev << ")"
+                            << " failed";
     }
     LOG(INFO) << "swapoff() took " << swap_timer;;
 
-    if (!android::base::WriteStringToFile("1", ZRAM_RESET)) {
-        LOG(ERROR) << "zram_backing_dev: reset (" << backing_dev << ")" << " failed";
-        return;
+    if (!WriteStringToFile("1", ZRAM_RESET)) {
+        return Error() << "zram_backing_dev: reset (" << backing_dev << ")"
+                       << " failed";
     }
 
     // clear loopback device
     unique_fd loop(TEMP_FAILURE_RETRY(open(backing_dev.c_str(), O_RDWR | O_CLOEXEC)));
     if (loop.get() < 0) {
-        LOG(ERROR) << "zram_backing_dev: open(" << backing_dev << ")" << " failed";
-        return;
+        return ErrnoError() << "zram_backing_dev: open(" << backing_dev << ")"
+                            << " failed";
     }
 
     if (ioctl(loop.get(), LOOP_CLR_FD, 0) < 0) {
-        LOG(ERROR) << "zram_backing_dev: loop_clear (" << backing_dev << ")" << " failed";
-        return;
+        return ErrnoError() << "zram_backing_dev: loop_clear (" << backing_dev << ")"
+                            << " failed";
     }
     LOG(INFO) << "zram_backing_dev: `" << backing_dev << "` is cleared successfully.";
+    return {};
+}
+
+// Stops given services, waits for them to be stopped for |timeout| ms.
+// If terminate is true, then SIGTERM is sent to services, otherwise SIGKILL is sent.
+static void StopServices(const std::vector<Service*>& services, std::chrono::milliseconds timeout,
+                         bool terminate) {
+    LOG(INFO) << "Stopping " << services.size() << " services by sending "
+              << (terminate ? "SIGTERM" : "SIGKILL");
+    std::vector<pid_t> pids;
+    pids.reserve(services.size());
+    for (const auto& s : services) {
+        if (s->pid() > 0) {
+            pids.push_back(s->pid());
+        }
+        if (terminate) {
+            s->Terminate();
+        } else {
+            s->Stop();
+        }
+    }
+    if (timeout > 0ms) {
+        WaitToBeReaped(pids, timeout);
+    } else {
+        // Even if we don't to wait for services to stop, we still optimistically reap zombies.
+        ReapAnyOutstandingChildren();
+    }
+}
+
+// Like StopServices, but also logs all the services that failed to stop after the provided timeout.
+// Returns number of violators.
+static int StopServicesAndLogViolations(const std::vector<Service*>& services,
+                                        std::chrono::milliseconds timeout, bool terminate) {
+    StopServices(services, timeout, terminate);
+    int still_running = 0;
+    for (const auto& s : services) {
+        if (s->IsRunning()) {
+            LOG(ERROR) << "[service-misbehaving] : service '" << s->name() << "' is still running "
+                       << timeout.count() << "ms after receiving "
+                       << (terminate ? "SIGTERM" : "SIGKILL");
+            still_running++;
+        }
+    }
+    return still_running;
 }
 
 //* Reboot / shutdown the system.
 // cmd ANDROID_RB_* as defined in android_reboot.h
 // reason Reason string like "reboot", "shutdown,userrequested"
-// rebootTarget Reboot target string like "bootloader". Otherwise, it should be an
-//              empty string.
-// runFsck Whether to run fsck after umount is done.
+// reboot_target Reboot target string like "bootloader". Otherwise, it should be an empty string.
+// run_fsck Whether to run fsck after umount is done.
 //
-static void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
-                     bool runFsck) {
+static void DoReboot(unsigned int cmd, const std::string& reason, const std::string& reboot_target,
+                     bool run_fsck) {
     Timer t;
-    LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
+    LOG(INFO) << "Reboot start, reason: " << reason << ", reboot_target: " << reboot_target;
+
+    // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
+    // worry about unmounting it.
+    if (!IsDataMounted()) {
+        sync();
+        RebootSystem(cmd, reboot_target);
+        abort();
+    }
 
     // Ensure last reboot reason is reduced to canonical
     // alias reported in bootloader or system boot reason.
@@ -351,7 +547,7 @@
          reasons[1] == "hard" || reasons[1] == "warm")) {
         skip = strlen("reboot,");
     }
-    property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
+    SetProperty(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
     sync();
 
     bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
@@ -369,12 +565,30 @@
     }
     LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
 
-    // keep debugging tools until non critical ones are all gone.
-    const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
+    sem_t reboot_semaphore;
+    if (sem_init(&reboot_semaphore, false, 0) == -1) {
+        // These should never fail, but if they do, skip the graceful reboot and reboot immediately.
+        LOG(ERROR) << "sem_init() fail and RebootSystem() return!";
+        RebootSystem(cmd, reboot_target);
+    }
+
+    // Start a thread to monitor init shutdown process
+    LOG(INFO) << "Create reboot monitor thread.";
+    bool reboot_monitor_run = true;
+    std::thread reboot_monitor_thread(&RebootMonitorThread, cmd, reboot_target, &reboot_semaphore,
+                                      shutdown_timeout, &reboot_monitor_run);
+    reboot_monitor_thread.detach();
+
+    // Start reboot monitor thread
+    sem_post(&reboot_semaphore);
+
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
     const std::set<std::string> to_starts{"watchdogd"};
+    std::vector<Service*> stop_first;
+    stop_first.reserve(ServiceList::GetInstance().services().size());
     for (const auto& s : ServiceList::GetInstance()) {
-        if (kill_after_apps.count(s->name())) {
+        if (kDebuggingServices.count(s->name())) {
+            // keep debugging tools until non critical ones are all gone.
             s->SetShutdownCritical();
         } else if (to_starts.count(s->name())) {
             if (auto result = s->Start(); !result) {
@@ -388,6 +602,8 @@
                 LOG(ERROR) << "Could not start shutdown critical service '" << s->name()
                            << "': " << result.error();
             }
+        } else {
+            stop_first.push_back(s.get());
         }
     }
 
@@ -396,16 +612,16 @@
         TurnOffBacklight();
     }
 
-    Service* bootAnim = ServiceList::GetInstance().FindService("bootanim");
-    Service* surfaceFlinger = ServiceList::GetInstance().FindService("surfaceflinger");
-    if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {
+    Service* boot_anim = ServiceList::GetInstance().FindService("bootanim");
+    Service* surface_flinger = ServiceList::GetInstance().FindService("surfaceflinger");
+    if (boot_anim != nullptr && surface_flinger != nullptr && surface_flinger->IsRunning()) {
         bool do_shutdown_animation = GetBoolProperty("ro.init.shutdown_animation", false);
 
         if (do_shutdown_animation) {
-            property_set("service.bootanim.exit", "0");
+            SetProperty("service.bootanim.exit", "0");
             // Could be in the middle of animation. Stop and start so that it can pick
             // up the right mode.
-            bootAnim->Stop();
+            boot_anim->Stop();
         }
 
         for (const auto& service : ServiceList::GetInstance()) {
@@ -415,78 +631,39 @@
 
             // start all animation classes if stopped.
             if (do_shutdown_animation) {
-                service->Start().IgnoreError();
+                service->Start();
             }
             service->SetShutdownCritical();  // will not check animation class separately
         }
 
         if (do_shutdown_animation) {
-            bootAnim->Start().IgnoreError();
-            surfaceFlinger->SetShutdownCritical();
-            bootAnim->SetShutdownCritical();
+            boot_anim->Start();
+            surface_flinger->SetShutdownCritical();
+            boot_anim->SetShutdownCritical();
         }
     }
 
     // optional shutdown step
     // 1. terminate all services except shutdown critical ones. wait for delay to finish
     if (shutdown_timeout > 0ms) {
-        LOG(INFO) << "terminating init services";
-
-        // Ask all services to terminate except shutdown critical ones.
-        for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
-            if (!s->IsShutdownCritical()) s->Terminate();
-        }
-
-        int service_count = 0;
-        // Only wait up to half of timeout here
-        auto termination_wait_timeout = shutdown_timeout / 2;
-        while (t.duration() < termination_wait_timeout) {
-            ReapAnyOutstandingChildren();
-
-            service_count = 0;
-            for (const auto& s : ServiceList::GetInstance()) {
-                // Count the number of services running except shutdown critical.
-                // Exclude the console as it will ignore the SIGTERM signal
-                // and not exit.
-                // Note: SVC_CONSOLE actually means "requires console" but
-                // it is only used by the shell.
-                if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
-                    service_count++;
-                }
-            }
-
-            if (service_count == 0) {
-                // All terminable services terminated. We can exit early.
-                break;
-            }
-
-            // Wait a bit before recounting the number or running services.
-            std::this_thread::sleep_for(50ms);
-        }
-        LOG(INFO) << "Terminating running services took " << t
-                  << " with remaining services:" << service_count;
+        StopServicesAndLogViolations(stop_first, shutdown_timeout / 2, true /* SIGTERM */);
     }
-
-    // minimum safety steps before restarting
-    // 2. kill all services except ones that are necessary for the shutdown sequence.
-    for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
-        if (!s->IsShutdownCritical()) s->Stop();
-    }
+    // Send SIGKILL to ones that didn't terminate cleanly.
+    StopServicesAndLogViolations(stop_first, 0ms, false /* SIGKILL */);
     SubcontextTerminate();
+    // Reap subcontext pids.
     ReapAnyOutstandingChildren();
 
     // 3. send volume shutdown to vold
-    Service* voldService = ServiceList::GetInstance().FindService("vold");
-    if (voldService != nullptr && voldService->IsRunning()) {
-        ShutdownVold();
-        voldService->Stop();
+    Service* vold_service = ServiceList::GetInstance().FindService("vold");
+    if (vold_service != nullptr && vold_service->IsRunning()) {
+        CallVdc("volume", "shutdown");
+        vold_service->Stop();
     } else {
         LOG(INFO) << "vold not running, skipping vold shutdown";
     }
     // logcat stopped here
-    for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
-        if (kill_after_apps.count(s->name())) s->Stop();
-    }
+    StopServices(GetDebuggingServices(false /* only_post_data */), 0ms, false /* SIGKILL */);
     // 4. sync, try umount, and optionally run fsck for user shutdown
     {
         Timer sync_timer;
@@ -497,7 +674,8 @@
     // 5. drop caches and disable zram backing device, if exist
     KillZramBackingDevice();
 
-    UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
+    UmountStat stat =
+            TryUmountAndFsck(cmd, run_fsck, shutdown_timeout - t.duration(), &reboot_semaphore);
     // Follow what linux shutdown is doing: one more sync with little bit delay
     {
         Timer sync_timer;
@@ -507,23 +685,192 @@
     }
     if (!is_thermal_shutdown) std::this_thread::sleep_for(100ms);
     LogShutdownTime(stat, &t);
+
+    // Send signal to terminate reboot monitor thread.
+    reboot_monitor_run = false;
+    sem_post(&reboot_semaphore);
+
     // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
-    RebootSystem(cmd, rebootTarget);
+    RebootSystem(cmd, reboot_target);
     abort();
 }
 
-bool HandlePowerctlMessage(const std::string& command) {
+static void EnterShutdown() {
+    LOG(INFO) << "Entering shutdown mode";
+    shutting_down = true;
+    // Skip wait for prop if it is in progress
+    ResetWaitForProp();
+    // Clear EXEC flag if there is one pending
+    for (const auto& s : ServiceList::GetInstance()) {
+        s->UnSetExec();
+    }
+    // We no longer process messages about properties changing coming from property service, so we
+    // need to tell property service to stop sending us these messages, otherwise it'll fill the
+    // buffers and block indefinitely, causing future property sets, including those that init makes
+    // during shutdown in Service::NotifyStateChange() to also block indefinitely.
+    SendStopSendingMessagesMessage();
+}
+
+static void LeaveShutdown() {
+    LOG(INFO) << "Leaving shutdown mode";
+    shutting_down = false;
+    SendStartSendingMessagesMessage();
+}
+
+static Result<void> UnmountAllApexes() {
+    const char* args[] = {"/system/bin/apexd", "--unmount-all"};
+    int status;
+    if (logwrap_fork_execvp(arraysize(args), args, &status, false, LOG_KLOG, true, nullptr) != 0) {
+        return ErrnoError() << "Failed to call '/system/bin/apexd --unmount-all'";
+    }
+    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+        return {};
+    }
+    return Error() << "'/system/bin/apexd --unmount-all' failed : " << status;
+}
+
+static Result<void> DoUserspaceReboot() {
+    LOG(INFO) << "Userspace reboot initiated";
+    boot_clock::time_point now = boot_clock::now();
+    SetProperty("sys.init.userspace_reboot.last_started",
+                std::to_string(now.time_since_epoch().count()));
+    auto guard = android::base::make_scope_guard([] {
+        // Leave shutdown so that we can handle a full reboot.
+        LeaveShutdown();
+        trigger_shutdown("reboot,abort-userspace-reboot");
+    });
+    // Triggering userspace-reboot-requested will result in a bunch of setprop
+    // actions. We should make sure, that all of them are propagated before
+    // proceeding with userspace reboot. Synchronously setting kUserspaceRebootInProgress property
+    // is not perfect, but it should do the trick.
+    if (!android::sysprop::InitProperties::userspace_reboot_in_progress(true)) {
+        return Error() << "Failed to set sys.init.userspace_reboot.in_progress property";
+    }
+    EnterShutdown();
+    std::vector<Service*> stop_first;
+    // Remember the services that were enabled. We will need to manually enable them again otherwise
+    // triggers like class_start won't restart them.
+    std::vector<Service*> were_enabled;
+    stop_first.reserve(ServiceList::GetInstance().services().size());
+    for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
+        if (s->is_post_data() && !kDebuggingServices.count(s->name())) {
+            stop_first.push_back(s);
+        }
+        if (s->is_post_data() && s->IsEnabled()) {
+            were_enabled.push_back(s);
+        }
+    }
+    {
+        Timer sync_timer;
+        LOG(INFO) << "sync() before terminating services...";
+        sync();
+        LOG(INFO) << "sync() took " << sync_timer;
+    }
+    // TODO(b/135984674): do we need shutdown animation for userspace reboot?
+    // TODO(b/135984674): control userspace timeout via read-only property?
+    StopServicesAndLogViolations(stop_first, 10s, true /* SIGTERM */);
+    if (int r = StopServicesAndLogViolations(stop_first, 20s, false /* SIGKILL */); r > 0) {
+        // TODO(b/135984674): store information about offending services for debugging.
+        return Error() << r << " post-data services are still running";
+    }
+    if (auto result = KillZramBackingDevice(); !result) {
+        return result;
+    }
+    if (auto result = CallVdc("volume", "reset"); !result) {
+        return result;
+    }
+    if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */), 5s,
+                                             false /* SIGKILL */);
+        r > 0) {
+        // TODO(b/135984674): store information about offending services for debugging.
+        return Error() << r << " debugging services are still running";
+    }
+    {
+        Timer sync_timer;
+        LOG(INFO) << "sync() after stopping services...";
+        sync();
+        LOG(INFO) << "sync() took " << sync_timer;
+    }
+    if (auto result = UnmountAllApexes(); !result) {
+        return result;
+    }
+    if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
+        return Error() << "Failed to switch to bootstrap namespace";
+    }
+    // Remove services that were defined in an APEX.
+    ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr<Service>& s) -> bool {
+        if (s->is_from_apex()) {
+            LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX";
+            return true;
+        }
+        return false;
+    });
+    // Re-enable services
+    for (const auto& s : were_enabled) {
+        LOG(INFO) << "Re-enabling service '" << s->name() << "'";
+        s->Enable();
+    }
+    LeaveShutdown();
+    ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume");
+    guard.Disable();  // Go on with userspace reboot.
+    return {};
+}
+
+static void UserspaceRebootWatchdogThread() {
+    if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", 20s)) {
+        // TODO(b/135984674): should we reboot instead?
+        LOG(WARNING) << "Userspace reboot didn't start in 20 seconds. Stopping watchdog";
+        return;
+    }
+    LOG(INFO) << "Starting userspace reboot watchdog";
+    // TODO(b/135984674): this should be configured via a read-only sysprop.
+    std::chrono::milliseconds timeout = 60s;
+    if (!WaitForProperty("sys.boot_completed", "1", timeout)) {
+        LOG(ERROR) << "Failed to boot in " << timeout.count() << "ms. Switching to full reboot";
+        // In this case device is in a boot loop. Only way to recover is to do dirty reboot.
+        RebootSystem(ANDROID_RB_RESTART2, "userspace-reboot-watchdog-triggered");
+    }
+    LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
+}
+
+static void HandleUserspaceReboot() {
+    if (!android::sysprop::InitProperties::is_userspace_reboot_supported().value_or(false)) {
+        LOG(ERROR) << "Attempted a userspace reboot on a device that doesn't support it";
+        return;
+    }
+    // Spinnig up a separate thread will fail the setns call later in the boot sequence.
+    // Fork a new process to monitor userspace reboot while we are investigating a better solution.
+    pid_t pid = fork();
+    if (pid < 0) {
+        PLOG(ERROR) << "Failed to fork process for userspace reboot watchdog. Switching to full "
+                    << "reboot";
+        trigger_shutdown("reboot,userspace-reboot-failed-to-fork");
+        return;
+    }
+    if (pid == 0) {
+        // Child
+        UserspaceRebootWatchdogThread();
+        _exit(EXIT_SUCCESS);
+    }
+    LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger";
+    auto& am = ActionManager::GetInstance();
+    am.ClearQueue();
+    am.QueueEventTrigger("userspace-reboot-requested");
+    auto handler = [](const BuiltinArguments&) { return DoUserspaceReboot(); };
+    am.QueueBuiltinAction(handler, "userspace-reboot");
+}
+
+void HandlePowerctlMessage(const std::string& command) {
     unsigned int cmd = 0;
     std::vector<std::string> cmd_params = Split(command, ",");
     std::string reboot_target = "";
     bool run_fsck = false;
     bool command_invalid = false;
+    bool userspace_reboot = false;
 
-    if (cmd_params.size() > 3) {
-        command_invalid = true;
-    } else if (cmd_params[0] == "shutdown") {
+    if (cmd_params[0] == "shutdown") {
         cmd = ANDROID_RB_POWEROFF;
-        if (cmd_params.size() == 2) {
+        if (cmd_params.size() >= 2) {
             if (cmd_params[1] == "userrequested") {
                 // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
                 // Run fsck once the file system is remounted in read-only mode.
@@ -539,6 +886,10 @@
         cmd = ANDROID_RB_RESTART2;
         if (cmd_params.size() >= 2) {
             reboot_target = cmd_params[1];
+            if (reboot_target == "userspace") {
+                LOG(INFO) << "Userspace reboot requested";
+                userspace_reboot = true;
+            }
             // adb reboot fastboot should boot into bootloader for devices not
             // supporting logical partitions.
             if (reboot_target == "fastboot" &&
@@ -554,6 +905,20 @@
                                   "bootloader_message: "
                                << err;
                 }
+            } else if (reboot_target == "recovery") {
+                bootloader_message boot = {};
+                if (std::string err; !read_bootloader_message(&boot, &err)) {
+                    LOG(ERROR) << "Failed to read bootloader message: " << err;
+                }
+                // Update the boot command field if it's empty, and preserve
+                // the other arguments in the bootloader message.
+                if (boot.command[0] == '\0') {
+                    strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
+                    if (std::string err; !write_bootloader_message(boot, &err)) {
+                        LOG(ERROR) << "Failed to set bootloader message: " << err;
+                        return;
+                    }
+                }
             } else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" ||
                        reboot_target == "fastboot") {
                 std::string arg = reboot_target == "sideload-auto-reboot" ? "sideload_auto_reboot"
@@ -564,14 +929,14 @@
                 std::string err;
                 if (!write_bootloader_message(options, &err)) {
                     LOG(ERROR) << "Failed to set bootloader message: " << err;
-                    return false;
+                    return;
                 }
                 reboot_target = "recovery";
             }
 
-            // If there is an additional parameter, pass it along
-            if ((cmd_params.size() == 3) && cmd_params[2].size()) {
-                reboot_target += "," + cmd_params[2];
+            // If there are additional parameter, pass them along
+            for (size_t i = 2; (cmd_params.size() > i) && cmd_params[i].size(); ++i) {
+                reboot_target += "," + cmd_params[i];
             }
         }
     } else {
@@ -579,7 +944,12 @@
     }
     if (command_invalid) {
         LOG(ERROR) << "powerctl: unrecognized command '" << command << "'";
-        return false;
+        return;
+    }
+
+    if (userspace_reboot) {
+        HandleUserspaceReboot();
+        return;
     }
 
     LOG(INFO) << "Clear action queue and start shutdown trigger";
@@ -589,19 +959,15 @@
     // Queue built-in shutdown_done
     auto shutdown_handler = [cmd, command, reboot_target, run_fsck](const BuiltinArguments&) {
         DoReboot(cmd, command, reboot_target, run_fsck);
-        return Success();
+        return Result<void>{};
     };
     ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done");
 
-    // Skip wait for prop if it is in progress
-    ResetWaitForProp();
+    EnterShutdown();
+}
 
-    // Clear EXEC flag if there is one pending
-    for (const auto& s : ServiceList::GetInstance()) {
-        s->UnSetExec();
-    }
-
-    return true;
+bool IsShuttingDown() {
+    return shutting_down;
 }
 
 }  // namespace init
diff --git a/init/reboot.h b/init/reboot.h
index 07dcb6e..81c3edc 100644
--- a/init/reboot.h
+++ b/init/reboot.h
@@ -23,8 +23,9 @@
 namespace init {
 
 // Parses and handles a setprop sys.powerctl message.
-bool HandlePowerctlMessage(const std::string& command);
+void HandlePowerctlMessage(const std::string& command);
 
+bool IsShuttingDown();
 }  // namespace init
 }  // namespace android
 
diff --git a/init/reboot_utils.cpp b/init/reboot_utils.cpp
index de085cc..dac0cf4 100644
--- a/init/reboot_utils.cpp
+++ b/init/reboot_utils.cpp
@@ -109,7 +109,7 @@
     abort();
 }
 
-void __attribute__((noreturn)) InitFatalReboot() {
+void __attribute__((noreturn)) InitFatalReboot(int signal_number) {
     auto pid = fork();
 
     if (pid == -1) {
@@ -124,6 +124,7 @@
     }
 
     // In the parent, let's try to get a backtrace then shutdown.
+    LOG(ERROR) << __FUNCTION__ << ": signal " << signal_number;
     std::unique_ptr<Backtrace> backtrace(
             Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
     if (!backtrace->Unwind(0)) {
@@ -154,7 +155,7 @@
         // RebootSystem uses syscall() which isn't actually async-signal-safe, but our only option
         // and probably good enough given this is already an error case and only enabled for
         // development builds.
-        InitFatalReboot();
+        InitFatalReboot(signal);
     };
     action.sa_flags = SA_RESTART;
     sigaction(SIGABRT, &action, nullptr);
diff --git a/init/reboot_utils.h b/init/reboot_utils.h
index 3fd969e..878ad96 100644
--- a/init/reboot_utils.h
+++ b/init/reboot_utils.h
@@ -27,7 +27,7 @@
 bool IsRebootCapable();
 // This is a wrapper around the actual reboot calls.
 void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& reboot_target);
-void __attribute__((noreturn)) InitFatalReboot();
+void __attribute__((noreturn)) InitFatalReboot(int signal_number);
 void InstallRebootSignalHandlers();
 
 }  // namespace init
diff --git a/init/result.h b/init/result.h
index 0e3fd3d..b70dd1b 100644
--- a/init/result.h
+++ b/init/result.h
@@ -14,200 +14,16 @@
  * limitations under the License.
  */
 
-// This file contains classes for returning a successful result along with an optional
-// arbitrarily typed return value or for returning a failure result along with an optional string
-// indicating why the function failed.
+#pragma once
 
-// There are 3 classes that implement this functionality and one additional helper type.
-//
-// Result<T> either contains a member of type T that can be accessed using similar semantics as
-// std::optional<T> or it contains a ResultError describing an error, which can be accessed via
-// Result<T>::error().
-//
-// ResultError is a type that contains both a std::string describing the error and a copy of errno
-// from when the error occurred.  ResultError can be used in an ostream directly to print its
-// string value.
-//
-// Success is a typedef that aids in creating Result<T> that do not contain a return value.
-// Result<Success> is the correct return type for a function that either returns successfully or
-// returns an error value.  Returning Success() from a function that returns Result<Success> is the
-// correct way to indicate that a function without a return type has completed successfully.
-//
-// A successful Result<T> is constructed implicitly from any type that can be implicitly converted
-// to T or from the constructor arguments for T.  This allows you to return a type T directly from
-// a function that returns Result<T>.
-//
-// Error and ErrnoError are used to construct a Result<T> that has failed.  The Error class takes
-// an ostream as an input and are implicitly cast to a Result<T> containing that failure.
-// ErrnoError() is a helper function to create an Error class that appends ": " + strerror(errno)
-// to the end of the failure string to aid in interacting with C APIs.  Alternatively, an errno
-// value can be directly specified via the Error() constructor.
-//
-// ResultError can be used in the ostream when using Error to construct a Result<T>.  In this case,
-// the string that the ResultError takes is passed through the stream normally, but the errno is
-// passed to the Result<T>.  This can be used to pass errno from a failing C function up multiple
-// callers.
-//
-// ResultError can also directly construct a Result<T>.  This is particularly useful if you have a
-// function that return Result<T> but you have a Result<U> and want to return its error.  In this
-// case, you can return the .error() from the Result<U> to construct the Result<T>.
+// The implementation of this file has moved to android-base.  This file remains since historically,
+// these classes were a part of init.
 
-// An example of how to use these is below:
-// Result<U> CalculateResult(const T& input) {
-//   U output;
-//   if (!SomeOtherCppFunction(input, &output)) {
-//     return Error() << "SomeOtherCppFunction(" << input << ") failed";
-//   }
-//   if (!c_api_function(output)) {
-//     return ErrnoError() << "c_api_function(" << output << ") failed";
-//   }
-//   return output;
-// }
-//
-// auto output = CalculateResult(input);
-// if (!output) return Error() << "CalculateResult failed: " << output.error();
-// UseOutput(*output);
+#include <android-base/result.h>
 
-#ifndef _INIT_RESULT_H
-#define _INIT_RESULT_H
-
-#include <errno.h>
-
-#include <sstream>
-#include <string>
-#include <variant>
-
-namespace android {
-namespace init {
-
-struct ResultError {
-    template <typename T>
-    ResultError(T&& error_string, int error_errno)
-        : error_string(std::forward<T>(error_string)), error_errno(error_errno) {}
-
-    std::string error_string;
-    int error_errno;
-};
-
-inline std::ostream& operator<<(std::ostream& os, const ResultError& t) {
-    os << t.error_string;
-    return os;
-}
-
-inline std::ostream& operator<<(std::ostream& os, ResultError&& t) {
-    os << std::move(t.error_string);
-    return os;
-}
-
-class Error {
-  public:
-    Error() : errno_(0), append_errno_(false) {}
-    Error(int errno_to_append) : errno_(errno_to_append), append_errno_(true) {}
-
-    template <typename T>
-    Error&& operator<<(T&& t) {
-        ss_ << std::forward<T>(t);
-        return std::move(*this);
-    }
-
-    Error&& operator<<(const ResultError& result_error) {
-        ss_ << result_error.error_string;
-        errno_ = result_error.error_errno;
-        return std::move(*this);
-    }
-
-    Error&& operator<<(ResultError&& result_error) {
-        ss_ << std::move(result_error.error_string);
-        errno_ = result_error.error_errno;
-        return std::move(*this);
-    }
-
-    const std::string str() const {
-        std::string str = ss_.str();
-        if (append_errno_) {
-            if (str.empty()) {
-                return strerror(errno_);
-            }
-            return str + ": " + strerror(errno_);
-        }
-        return str;
-    }
-
-    int get_errno() const { return errno_; }
-
-    Error(const Error&) = delete;
-    Error(Error&&) = delete;
-    Error& operator=(const Error&) = delete;
-    Error& operator=(Error&&) = delete;
-
-  private:
-    std::stringstream ss_;
-    int errno_;
-    bool append_errno_;
-};
-
-inline Error ErrnoError() {
-    return Error(errno);
-}
-
-template <typename T>
-class [[nodiscard]] Result {
-  public:
-    Result() {}
-
-    template <typename U, typename... V,
-              typename = std::enable_if_t<!(std::is_same_v<std::decay_t<U>, Result<T>> &&
-                                            sizeof...(V) == 0)>>
-    Result(U&& result, V&&... results)
-        : contents_(std::in_place_index_t<0>(), std::forward<U>(result),
-                    std::forward<V>(results)...) {}
-
-    Result(Error&& error) : contents_(std::in_place_index_t<1>(), error.str(), error.get_errno()) {}
-    Result(const ResultError& result_error)
-        : contents_(std::in_place_index_t<1>(), result_error.error_string,
-                    result_error.error_errno) {}
-    Result(ResultError&& result_error)
-        : contents_(std::in_place_index_t<1>(), std::move(result_error.error_string),
-                    result_error.error_errno) {}
-
-    void IgnoreError() const {}
-
-    bool has_value() const { return contents_.index() == 0; }
-
-    T& value() & { return std::get<0>(contents_); }
-    const T& value() const & { return std::get<0>(contents_); }
-    T&& value() && { return std::get<0>(std::move(contents_)); }
-    const T&& value() const && { return std::get<0>(std::move(contents_)); }
-
-    const ResultError& error() const & { return std::get<1>(contents_); }
-    ResultError&& error() && { return std::get<1>(std::move(contents_)); }
-    const ResultError&& error() const && { return std::get<1>(std::move(contents_)); }
-
-    const std::string& error_string() const & { return std::get<1>(contents_).error_string; }
-    std::string&& error_string() && { return std::get<1>(std::move(contents_)).error_string; }
-    const std::string&& error_string() const && {
-        return std::get<1>(std::move(contents_)).error_string;
-    }
-
-    int error_errno() const { return std::get<1>(contents_).error_errno; }
-
-    explicit operator bool() const { return has_value(); }
-
-    T& operator*() & { return value(); }
-    const T& operator*() const & { return value(); }
-    T&& operator*() && { return std::move(value()); }
-    const T&& operator*() const && { return std::move(value()); }
-
-    T* operator->() { return &value(); }
-    const T* operator->() const { return &value(); }
-
-  private:
-    std::variant<T, ResultError> contents_;
-};
-
-using Success = std::monostate;
-
-}  // namespace init
-}  // namespace android
-
-#endif
+using android::base::ErrnoError;
+using android::base::ErrnoErrorf;
+using android::base::Error;
+using android::base::Errorf;
+using android::base::Result;
+using android::base::ResultError;
diff --git a/init/result_test.cpp b/init/result_test.cpp
deleted file mode 100644
index 327b444..0000000
--- a/init/result_test.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2017 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 "result.h"
-
-#include "errno.h"
-
-#include <string>
-
-#include <gtest/gtest.h>
-
-using namespace std::string_literals;
-
-namespace android {
-namespace init {
-
-TEST(result, result_accessors) {
-    Result<std::string> result = "success";
-    ASSERT_TRUE(result);
-    ASSERT_TRUE(result.has_value());
-
-    EXPECT_EQ("success", *result);
-    EXPECT_EQ("success", result.value());
-
-    EXPECT_EQ('s', result->data()[0]);
-}
-
-TEST(result, result_accessors_rvalue) {
-    ASSERT_TRUE(Result<std::string>("success"));
-    ASSERT_TRUE(Result<std::string>("success").has_value());
-
-    EXPECT_EQ("success", *Result<std::string>("success"));
-    EXPECT_EQ("success", Result<std::string>("success").value());
-
-    EXPECT_EQ('s', Result<std::string>("success")->data()[0]);
-}
-
-TEST(result, result_success) {
-    Result<Success> result = Success();
-    ASSERT_TRUE(result);
-    ASSERT_TRUE(result.has_value());
-
-    EXPECT_EQ(Success(), *result);
-    EXPECT_EQ(Success(), result.value());
-}
-
-TEST(result, result_success_rvalue) {
-    // Success() doesn't actually create a Result<Success> object, but rather an object that can be
-    // implicitly constructed into a Result<Success> object.
-
-    auto MakeRvalueSuccessResult = []() -> Result<Success> { return Success(); };
-    ASSERT_TRUE(MakeRvalueSuccessResult());
-    ASSERT_TRUE(MakeRvalueSuccessResult().has_value());
-
-    EXPECT_EQ(Success(), *MakeRvalueSuccessResult());
-    EXPECT_EQ(Success(), MakeRvalueSuccessResult().value());
-}
-
-TEST(result, result_error) {
-    Result<Success> result = Error() << "failure" << 1;
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    EXPECT_EQ(0, result.error_errno());
-    EXPECT_EQ("failure1", result.error_string());
-}
-
-TEST(result, result_error_empty) {
-    Result<Success> result = Error();
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    EXPECT_EQ(0, result.error_errno());
-    EXPECT_EQ("", result.error_string());
-}
-
-TEST(result, result_error_rvalue) {
-    // Error() and ErrnoError() aren't actually used to create a Result<T> object.
-    // Under the hood, they are an intermediate class that can be implicitly constructed into a
-    // Result<T>.  This is needed both to create the ostream and because Error() itself, by
-    // definition will not know what the type, T, of the underlying Result<T> object that it would
-    // create is.
-
-    auto MakeRvalueErrorResult = []() -> Result<Success> { return Error() << "failure" << 1; };
-    ASSERT_FALSE(MakeRvalueErrorResult());
-    ASSERT_FALSE(MakeRvalueErrorResult().has_value());
-
-    EXPECT_EQ(0, MakeRvalueErrorResult().error_errno());
-    EXPECT_EQ("failure1", MakeRvalueErrorResult().error_string());
-}
-
-TEST(result, result_errno_error) {
-    constexpr int test_errno = 6;
-    errno = test_errno;
-    Result<Success> result = ErrnoError() << "failure" << 1;
-
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    EXPECT_EQ(test_errno, result.error_errno());
-    EXPECT_EQ("failure1: "s + strerror(test_errno), result.error_string());
-}
-
-TEST(result, result_errno_error_no_text) {
-    constexpr int test_errno = 6;
-    errno = test_errno;
-    Result<Success> result = ErrnoError();
-
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    EXPECT_EQ(test_errno, result.error_errno());
-    EXPECT_EQ(strerror(test_errno), result.error_string());
-}
-
-TEST(result, result_error_from_other_result) {
-    auto error_text = "test error"s;
-    Result<Success> result = Error() << error_text;
-
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    Result<std::string> result2 = result.error();
-
-    ASSERT_FALSE(result2);
-    ASSERT_FALSE(result2.has_value());
-
-    EXPECT_EQ(0, result.error_errno());
-    EXPECT_EQ(error_text, result.error_string());
-}
-
-TEST(result, result_error_through_ostream) {
-    auto error_text = "test error"s;
-    Result<Success> result = Error() << error_text;
-
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    Result<std::string> result2 = Error() << result.error();
-
-    ASSERT_FALSE(result2);
-    ASSERT_FALSE(result2.has_value());
-
-    EXPECT_EQ(0, result.error_errno());
-    EXPECT_EQ(error_text, result.error_string());
-}
-
-TEST(result, result_errno_error_through_ostream) {
-    auto error_text = "test error"s;
-    constexpr int test_errno = 6;
-    errno = 6;
-    Result<Success> result = ErrnoError() << error_text;
-
-    errno = 0;
-
-    ASSERT_FALSE(result);
-    ASSERT_FALSE(result.has_value());
-
-    Result<std::string> result2 = Error() << result.error();
-
-    ASSERT_FALSE(result2);
-    ASSERT_FALSE(result2.has_value());
-
-    EXPECT_EQ(test_errno, result.error_errno());
-    EXPECT_EQ(error_text + ": " + strerror(test_errno), result.error_string());
-}
-
-TEST(result, constructor_forwarding) {
-    auto result = Result<std::string>(5, 'a');
-
-    ASSERT_TRUE(result);
-    ASSERT_TRUE(result.has_value());
-
-    EXPECT_EQ("aaaaa", *result);
-}
-
-struct ConstructorTracker {
-    static size_t constructor_called;
-    static size_t copy_constructor_called;
-    static size_t move_constructor_called;
-    static size_t copy_assignment_called;
-    static size_t move_assignment_called;
-
-    template <typename T>
-    ConstructorTracker(T&& string) : string(string) {
-        ++constructor_called;
-    }
-
-    ConstructorTracker(const ConstructorTracker& ct) {
-        ++copy_constructor_called;
-        string = ct.string;
-    }
-    ConstructorTracker(ConstructorTracker&& ct) noexcept {
-        ++move_constructor_called;
-        string = std::move(ct.string);
-    }
-    ConstructorTracker& operator=(const ConstructorTracker& ct) {
-        ++copy_assignment_called;
-        string = ct.string;
-        return *this;
-    }
-    ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
-        ++move_assignment_called;
-        string = std::move(ct.string);
-        return *this;
-    }
-
-    std::string string;
-};
-
-size_t ConstructorTracker::constructor_called = 0;
-size_t ConstructorTracker::copy_constructor_called = 0;
-size_t ConstructorTracker::move_constructor_called = 0;
-size_t ConstructorTracker::copy_assignment_called = 0;
-size_t ConstructorTracker::move_assignment_called = 0;
-
-Result<ConstructorTracker> ReturnConstructorTracker(const std::string& in) {
-    if (in.empty()) {
-        return "literal string";
-    }
-    if (in == "test2") {
-        return ConstructorTracker(in + in + "2");
-    }
-    ConstructorTracker result(in + " " + in);
-    return result;
-};
-
-TEST(result, no_copy_on_return) {
-    // If returning parameters that may be used to implicitly construct the type T of Result<T>,
-    // then those parameters are forwarded to the construction of Result<T>.
-
-    // If returning an prvalue or xvalue, it will be move constructed during the construction of
-    // Result<T>.
-
-    // This check ensures that that is the case, and particularly that no copy constructors
-    // are called.
-
-    auto result1 = ReturnConstructorTracker("");
-    ASSERT_TRUE(result1);
-    EXPECT_EQ("literal string", result1->string);
-    EXPECT_EQ(1U, ConstructorTracker::constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
-    EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
-
-    auto result2 = ReturnConstructorTracker("test2");
-    ASSERT_TRUE(result2);
-    EXPECT_EQ("test2test22", result2->string);
-    EXPECT_EQ(2U, ConstructorTracker::constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
-    EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
-    EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
-
-    auto result3 = ReturnConstructorTracker("test3");
-    ASSERT_TRUE(result3);
-    EXPECT_EQ("test3 test3", result3->string);
-    EXPECT_EQ(3U, ConstructorTracker::constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
-    EXPECT_EQ(2U, ConstructorTracker::move_constructor_called);
-    EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
-    EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
-}
-
-// Below two tests require that we do not hide the move constructor with our forwarding reference
-// constructor.  This is done with by disabling the forwarding reference constructor if its first
-// and only type is Result<T>.
-TEST(result, result_result_with_success) {
-    auto return_result_result_with_success = []() -> Result<Result<Success>> {
-        return Result<Success>();
-    };
-    auto result = return_result_result_with_success();
-    ASSERT_TRUE(result);
-    ASSERT_TRUE(*result);
-
-    auto inner_result = result.value();
-    ASSERT_TRUE(inner_result);
-}
-
-TEST(result, result_result_with_failure) {
-    auto return_result_result_with_error = []() -> Result<Result<Success>> {
-        return Result<Success>(ResultError("failure string", 6));
-    };
-    auto result = return_result_result_with_error();
-    ASSERT_TRUE(result);
-    ASSERT_FALSE(*result);
-    EXPECT_EQ("failure string", result->error_string());
-    EXPECT_EQ(6, result->error_errno());
-}
-
-// This test requires that we disable the forwarding reference constructor if Result<T> is the
-// *only* type that we are forwarding.  In otherwords, if we are forwarding Result<T>, int to
-// construct a Result<T>, then we still need the constructor.
-TEST(result, result_two_parameter_constructor_same_type) {
-    struct TestStruct {
-        TestStruct(int value) : value_(value) {}
-        TestStruct(Result<TestStruct> result, int value) : value_(result->value_ * value) {}
-        int value_;
-    };
-
-    auto return_test_struct = []() -> Result<TestStruct> { return {Result<TestStruct>(6), 6}; };
-
-    auto result = return_test_struct();
-    ASSERT_TRUE(result);
-    EXPECT_EQ(36, result->value_);
-}
-
-TEST(result, die_on_access_failed_result) {
-    Result<std::string> result = Error();
-    ASSERT_DEATH(*result, "");
-}
-
-TEST(result, die_on_get_error_succesful_result) {
-    Result<std::string> result = "success";
-    ASSERT_DEATH(result.error_string(), "");
-}
-
-}  // namespace init
-}  // namespace android
diff --git a/init/rlimit_parser.cpp b/init/rlimit_parser.cpp
index 1e0754a..476a46a 100644
--- a/init/rlimit_parser.cpp
+++ b/init/rlimit_parser.cpp
@@ -77,7 +77,7 @@
         return Error() << "Could not parse hard limit '" << args[3] << "'";
     }
 
-    return {resource, limit};
+    return std::pair{resource, limit};
 }
 
 }  // namespace init
diff --git a/init/rlimit_parser_test.cpp b/init/rlimit_parser_test.cpp
index 659ba8a..6a16d3b 100644
--- a/init/rlimit_parser_test.cpp
+++ b/init/rlimit_parser_test.cpp
@@ -43,8 +43,8 @@
     auto result = ParseRlimit(input);
 
     ASSERT_FALSE(result) << "input: " << input[1];
-    EXPECT_EQ(expected_result, result.error_string());
-    EXPECT_EQ(0, result.error_errno());
+    EXPECT_EQ(expected_result, result.error().message());
+    EXPECT_EQ(0, result.error().code());
 }
 
 TEST(rlimit, RlimitSuccess) {
diff --git a/init/security.cpp b/init/security.cpp
index a3494a2..586d0c7 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -43,14 +43,14 @@
 // devices/configurations where these I/O operations are blocking for a long
 // time. We do not reboot or halt on failures, as this is a best-effort
 // attempt.
-Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
+Result<void> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
     unique_fd hwrandom_fd(
         TEMP_FAILURE_RETRY(open("/dev/hw_random", O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
     if (hwrandom_fd == -1) {
         if (errno == ENOENT) {
             LOG(INFO) << "/dev/hw_random not found";
             // It's not an error to not have a Hardware RNG.
-            return Success();
+            return {};
         }
         return ErrnoError() << "Failed to open /dev/hw_random";
     }
@@ -80,10 +80,10 @@
     }
 
     LOG(INFO) << "Mixed " << total_bytes_written << " bytes from /dev/hw_random into /dev/urandom";
-    return Success();
+    return {};
 }
 
-static bool SetHighestAvailableOptionValue(std::string path, int min, int max) {
+static bool SetHighestAvailableOptionValue(const std::string& path, int min, int max) {
     std::ifstream inf(path, std::fstream::in);
     if (!inf) {
         LOG(ERROR) << "Cannot open for reading: " << path;
@@ -147,31 +147,31 @@
 // 9e08f57d684a x86: mm: support ARCH_MMAP_RND_BITS
 // ec9ee4acd97c drivers: char: random: add get_random_long()
 // 5ef11c35ce86 mm: ASLR: use get_random_long()
-Result<Success> SetMmapRndBitsAction(const BuiltinArguments&) {
+Result<void> SetMmapRndBitsAction(const BuiltinArguments&) {
 // values are arch-dependent
 #if defined(USER_MODE_LINUX)
     // uml does not support mmap_rnd_bits
-    return Success();
+    return {};
 #elif defined(__aarch64__)
     // arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE
     if (SetMmapRndBitsMin(33, 24, false) && SetMmapRndBitsMin(16, 16, true)) {
-        return Success();
+        return {};
     }
 #elif defined(__x86_64__)
     // x86_64 supports 28 - 32 bits
     if (SetMmapRndBitsMin(32, 32, false) && SetMmapRndBitsMin(16, 16, true)) {
-        return Success();
+        return {};
     }
 #elif defined(__arm__) || defined(__i386__)
     // check to see if we're running on 64-bit kernel
     bool h64 = !access(MMAP_RND_COMPAT_PATH, F_OK);
     // supported 32-bit architecture must have 16 bits set
     if (SetMmapRndBitsMin(16, 16, h64)) {
-        return Success();
+        return {};
     }
 #elif defined(__mips__) || defined(__mips64__)
     // TODO: add mips support b/27788820
-    return Success();
+    return {};
 #else
     LOG(ERROR) << "Unknown architecture";
 #endif
@@ -187,14 +187,14 @@
 // Set kptr_restrict to the highest available level.
 //
 // Aborts if unable to set this to an acceptable value.
-Result<Success> SetKptrRestrictAction(const BuiltinArguments&) {
+Result<void> SetKptrRestrictAction(const BuiltinArguments&) {
     std::string path = KPTR_RESTRICT_PATH;
 
     if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
         LOG(FATAL) << "Unable to set adequate kptr_restrict value!";
         return Error();
     }
-    return Success();
+    return {};
 }
 
 }  // namespace init
diff --git a/init/security.h b/init/security.h
index 6f6b944..b081a05 100644
--- a/init/security.h
+++ b/init/security.h
@@ -26,9 +26,9 @@
 namespace android {
 namespace init {
 
-Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&);
-Result<Success> SetMmapRndBitsAction(const BuiltinArguments&);
-Result<Success> SetKptrRestrictAction(const BuiltinArguments&);
+Result<void> MixHwrngIntoLinuxRngAction(const BuiltinArguments&);
+Result<void> SetMmapRndBitsAction(const BuiltinArguments&);
+Result<void> SetKptrRestrictAction(const BuiltinArguments&);
 
 }  // namespace init
 }  // namespace android
diff --git a/init/selabel.cpp b/init/selabel.cpp
new file mode 100644
index 0000000..daeb832
--- /dev/null
+++ b/init/selabel.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 "selabel.h"
+
+#include <selinux/android.h>
+
+namespace android {
+namespace init {
+
+namespace {
+
+selabel_handle* sehandle = nullptr;
+}
+
+// selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
+// its value.  selinux_android_restorecon() also needs an sehandle for file context look up.  It
+// will create and store its own copy, but selinux_android_set_sehandle() can be used to provide
+// one, thus eliminating an extra call to selinux_android_file_context_handle().
+void SelabelInitialize() {
+    sehandle = selinux_android_file_context_handle();
+    selinux_android_set_sehandle(sehandle);
+}
+
+// A C++ wrapper around selabel_lookup() using the cached sehandle.
+// If sehandle is null, this returns success with an empty context.
+bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
+    result->clear();
+
+    if (!sehandle) return true;
+
+    char* context;
+    if (selabel_lookup(sehandle, &context, key.c_str(), type) != 0) {
+        return false;
+    }
+    *result = context;
+    free(context);
+    return true;
+}
+
+// A C++ wrapper around selabel_lookup_best_match() using the cached sehandle.
+// If sehandle is null, this returns success with an empty context.
+bool SelabelLookupFileContextBestMatch(const std::string& key,
+                                       const std::vector<std::string>& aliases, int type,
+                                       std::string* result) {
+    result->clear();
+
+    if (!sehandle) return true;
+
+    std::vector<const char*> c_aliases;
+    for (const auto& alias : aliases) {
+        c_aliases.emplace_back(alias.c_str());
+    }
+    c_aliases.emplace_back(nullptr);
+
+    char* context;
+    if (selabel_lookup_best_match(sehandle, &context, key.c_str(), &c_aliases[0], type) != 0) {
+        return false;
+    }
+    *result = context;
+    free(context);
+    return true;
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/fs_mgr/libfiemap_writer/utility.h b/init/selabel.h
similarity index 64%
copy from fs_mgr/libfiemap_writer/utility.h
copy to init/selabel.h
index 2d418da..5d590b2 100644
--- a/fs_mgr/libfiemap_writer/utility.h
+++ b/init/selabel.h
@@ -17,14 +17,16 @@
 #pragma once
 
 #include <string>
+#include <vector>
 
 namespace android {
-namespace fiemap_writer {
+namespace init {
 
-// Given a file that will be created, determine the maximum size its containing
-// filesystem allows. Note this is a theoretical maximum size; free space is
-// ignored entirely.
-uint64_t DetermineMaximumFileSize(const std::string& file_path);
+void SelabelInitialize();
+bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
+bool SelabelLookupFileContextBestMatch(const std::string& key,
+                                       const std::vector<std::string>& aliases, int type,
+                                       std::string* result);
 
-}  // namespace fiemap_writer
+}  // namespace init
 }  // namespace android
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 86238b4..852d6ca 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -36,21 +36,25 @@
 // The split SEPolicy is loaded as described below:
 // 1) There is a precompiled SEPolicy located at either /vendor/etc/selinux/precompiled_sepolicy or
 //    /odm/etc/selinux/precompiled_sepolicy if odm parition is present.  Stored along with this file
-//    are the sha256 hashes of the parts of the SEPolicy on /system and /product that were used to
-//    compile this precompiled policy.  The system partition contains a similar sha256 of the parts
-//    of the SEPolicy that it currently contains.  Symmetrically, product paritition contains a
-//    sha256 of its SEPolicy.  System loads this precompiled_sepolicy directly if and only if hashes
-//    for system policy match and hashes for product policy match.
-// 2) If these hashes do not match, then either /system or /product (or both) have been updated out
-//    of sync with /vendor and the init needs to compile the SEPolicy.  /system contains the
-//    SEPolicy compiler, secilc, and it is used by the LoadSplitPolicy() function below to compile
-//    the SEPolicy to a temp directory and load it.  That function contains even more documentation
-//    with the specific implementation details of how the SEPolicy is compiled if needed.
+//    are the sha256 hashes of the parts of the SEPolicy on /system, /system_ext and /product that
+//    were used to compile this precompiled policy.  The system partition contains a similar sha256
+//    of the parts of the SEPolicy that it currently contains.  Symmetrically, system_ext and
+//    product paritition contain sha256 hashes of their SEPolicy.  The init loads this
+//    precompiled_sepolicy directly if and only if the hashes along with the precompiled SEPolicy on
+//    /vendor or /odm match the hashes for system, system_ext and product SEPolicy, respectively.
+// 2) If these hashes do not match, then either /system or /system_ext or /product (or some of them)
+//    have been updated out of sync with /vendor (or /odm if it is present) and the init needs to
+//    compile the SEPolicy.  /system contains the SEPolicy compiler, secilc, and it is used by the
+//    LoadSplitPolicy() function below to compile the SEPolicy to a temp directory and load it.
+//    That function contains even more documentation with the specific implementation details of how
+//    the SEPolicy is compiled if needed.
 
 #include "selinux.h"
 
 #include <android/api-level.h>
 #include <fcntl.h>
+#include <linux/audit.h>
+#include <linux/netlink.h>
 #include <stdlib.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -79,19 +83,16 @@
 
 namespace {
 
-selabel_handle* sehandle = nullptr;
-
 enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
 
 EnforcingStatus StatusFromCmdline() {
     EnforcingStatus status = SELINUX_ENFORCING;
 
-    import_kernel_cmdline(false,
-                          [&](const std::string& key, const std::string& value, bool in_qemu) {
-                              if (key == "androidboot.selinux" && value == "permissive") {
-                                  status = SELINUX_PERMISSIVE;
-                              }
-                          });
+    ImportKernelCmdline([&](const std::string& key, const std::string& value) {
+        if (key == "androidboot.selinux" && value == "permissive") {
+            status = SELINUX_PERMISSIVE;
+        }
+    });
 
     return status;
 }
@@ -228,6 +229,13 @@
                       "/system/etc/selinux/plat_sepolicy_and_mapping.sha256";
         return false;
     }
+    std::string actual_system_ext_id;
+    if (!ReadFirstLine("/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
+                       &actual_system_ext_id)) {
+        PLOG(INFO) << "Failed to read "
+                      "/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256";
+        return false;
+    }
     std::string actual_product_id;
     if (!ReadFirstLine("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
                        &actual_product_id)) {
@@ -243,6 +251,13 @@
         file->clear();
         return false;
     }
+    std::string precompiled_system_ext_id;
+    std::string precompiled_system_ext_sha256 = *file + ".system_ext_sepolicy_and_mapping.sha256";
+    if (!ReadFirstLine(precompiled_system_ext_sha256.c_str(), &precompiled_system_ext_id)) {
+        PLOG(INFO) << "Failed to read " << precompiled_system_ext_sha256;
+        file->clear();
+        return false;
+    }
     std::string precompiled_product_id;
     std::string precompiled_product_sha256 = *file + ".product_sepolicy_and_mapping.sha256";
     if (!ReadFirstLine(precompiled_product_sha256.c_str(), &precompiled_product_id)) {
@@ -251,6 +266,7 @@
         return false;
     }
     if (actual_plat_id.empty() || actual_plat_id != precompiled_plat_id ||
+        actual_system_ext_id.empty() || actual_system_ext_id != precompiled_system_ext_id ||
         actual_product_id.empty() || actual_product_id != precompiled_product_id) {
         file->clear();
         return false;
@@ -330,6 +346,23 @@
     }
     std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
 
+    std::string plat_compat_cil_file("/system/etc/selinux/mapping/" + vend_plat_vers +
+                                     ".compat.cil");
+    if (access(plat_compat_cil_file.c_str(), F_OK) == -1) {
+        plat_compat_cil_file.clear();
+    }
+
+    std::string system_ext_policy_cil_file("/system_ext/etc/selinux/system_ext_sepolicy.cil");
+    if (access(system_ext_policy_cil_file.c_str(), F_OK) == -1) {
+        system_ext_policy_cil_file.clear();
+    }
+
+    std::string system_ext_mapping_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +
+                                        ".cil");
+    if (access(system_ext_mapping_file.c_str(), F_OK) == -1) {
+        system_ext_mapping_file.clear();
+    }
+
     std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");
     if (access(product_policy_cil_file.c_str(), F_OK) == -1) {
         product_policy_cil_file.clear();
@@ -375,6 +408,15 @@
     };
     // clang-format on
 
+    if (!plat_compat_cil_file.empty()) {
+        compile_args.push_back(plat_compat_cil_file.c_str());
+    }
+    if (!system_ext_policy_cil_file.empty()) {
+        compile_args.push_back(system_ext_policy_cil_file.c_str());
+    }
+    if (!system_ext_mapping_file.empty()) {
+        compile_args.push_back(system_ext_mapping_file.c_str());
+    }
     if (!product_policy_cil_file.empty()) {
         compile_args.push_back(product_policy_cil_file.c_str());
     }
@@ -421,8 +463,6 @@
 }
 
 void SelinuxInitialize() {
-    Timer t;
-
     LOG(INFO) << "Loading SELinux policy";
     if (!LoadPolicy()) {
         LOG(FATAL) << "Unable to load SELinux policy";
@@ -432,23 +472,47 @@
     bool is_enforcing = IsEnforcing();
     if (kernel_enforcing != is_enforcing) {
         if (security_setenforce(is_enforcing)) {
-            PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
+            PLOG(FATAL) << "security_setenforce(" << (is_enforcing ? "true" : "false")
+                        << ") failed";
         }
     }
 
     if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
         LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
     }
+}
 
-    // init's first stage can't set properties, so pass the time to the second stage.
-    setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
+constexpr size_t kKlogMessageSize = 1024;
+
+void SelinuxAvcLog(char* buf, size_t buf_len) {
+    CHECK_GT(buf_len, 0u);
+
+    size_t str_len = strnlen(buf, buf_len);
+    // trim newline at end of string
+    if (buf[str_len - 1] == '\n') {
+        buf[str_len - 1] = '\0';
+    }
+
+    struct NetlinkMessage {
+        nlmsghdr hdr;
+        char buf[kKlogMessageSize];
+    } request = {};
+
+    request.hdr.nlmsg_flags = NLM_F_REQUEST;
+    request.hdr.nlmsg_type = AUDIT_USER_AVC;
+    request.hdr.nlmsg_len = sizeof(request);
+    strlcpy(request.buf, buf, sizeof(request.buf));
+
+    auto fd = unique_fd{socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT)};
+    if (!fd.ok()) {
+        return;
+    }
+
+    TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0));
 }
 
 }  // namespace
 
-// The files and directories that were created before initial sepolicy load or
-// files on ramdisk need to have their security context restored to the proper
-// value. This must happen before /dev is populated by ueventd.
 void SelinuxRestoreContext() {
     LOG(INFO) << "Running restorecon...";
     selinux_android_restorecon("/dev", 0);
@@ -467,6 +531,8 @@
     selinux_android_restorecon("/dev/device-mapper", 0);
 
     selinux_android_restorecon("/apex", 0);
+
+    selinux_android_restorecon("/linkerconfig", 0);
 }
 
 int SelinuxKlogCallback(int type, const char* fmt, ...) {
@@ -476,53 +542,63 @@
     } else if (type == SELINUX_INFO) {
         severity = android::base::INFO;
     }
-    char buf[1024];
+    char buf[kKlogMessageSize];
     va_list ap;
     va_start(ap, fmt);
-    vsnprintf(buf, sizeof(buf), fmt, ap);
+    int length_written = vsnprintf(buf, sizeof(buf), fmt, ap);
     va_end(ap);
-    android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
+    if (length_written <= 0) {
+        return 0;
+    }
+    if (type == SELINUX_AVC) {
+        SelinuxAvcLog(buf, sizeof(buf));
+    } else {
+        android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
+    }
     return 0;
 }
 
-// This function sets up SELinux logging to be written to kmsg, to match init's logging.
 void SelinuxSetupKernelLogging() {
     selinux_callback cb;
     cb.func_log = SelinuxKlogCallback;
     selinux_set_callback(SELINUX_CB_LOG, cb);
 }
 
-// This function returns the Android version with which the vendor SEPolicy was compiled.
-// It is used for version checks such as whether or not vendor_init should be used
 int SelinuxGetVendorAndroidVersion() {
-    if (!IsSplitPolicyDevice()) {
-        // If this device does not split sepolicy files, it's not a Treble device and therefore,
-        // we assume it's always on the latest platform.
-        return __ANDROID_API_FUTURE__;
-    }
+    static int vendor_android_version = [] {
+        if (!IsSplitPolicyDevice()) {
+            // If this device does not split sepolicy files, it's not a Treble device and therefore,
+            // we assume it's always on the latest platform.
+            return __ANDROID_API_FUTURE__;
+        }
 
-    std::string version;
-    if (!GetVendorMappingVersion(&version)) {
-        LOG(FATAL) << "Could not read vendor SELinux version";
-    }
+        std::string version;
+        if (!GetVendorMappingVersion(&version)) {
+            LOG(FATAL) << "Could not read vendor SELinux version";
+        }
 
-    int major_version;
-    std::string major_version_str(version, 0, version.find('.'));
-    if (!ParseInt(major_version_str, &major_version)) {
-        PLOG(FATAL) << "Failed to parse the vendor sepolicy major version " << major_version_str;
-    }
+        int major_version;
+        std::string major_version_str(version, 0, version.find('.'));
+        if (!ParseInt(major_version_str, &major_version)) {
+            PLOG(FATAL) << "Failed to parse the vendor sepolicy major version "
+                        << major_version_str;
+        }
 
-    return major_version;
+        return major_version;
+    }();
+    return vendor_android_version;
 }
 
-// This function initializes SELinux then execs init to run in the init SELinux context.
 int SetupSelinux(char** argv) {
+    SetStdioToDevNull(argv);
     InitKernelLogging(argv);
 
     if (REBOOT_BOOTLOADER_ON_PANIC) {
         InstallRebootSignalHandlers();
     }
 
+    boot_clock::time_point start_time = boot_clock::now();
+
     // Set up SELinux, loading the SELinux policy.
     SelinuxSetupKernelLogging();
     SelinuxInitialize();
@@ -535,6 +611,8 @@
         PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
     }
 
+    setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);
+
     const char* path = "/system/bin/init";
     const char* args[] = {path, "second_stage", nullptr};
     execv(path, const_cast<char**>(args));
@@ -546,54 +624,5 @@
     return 1;
 }
 
-// selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
-// its value.  selinux_android_restorecon() also needs an sehandle for file context look up.  It
-// will create and store its own copy, but selinux_android_set_sehandle() can be used to provide
-// one, thus eliminating an extra call to selinux_android_file_context_handle().
-void SelabelInitialize() {
-    sehandle = selinux_android_file_context_handle();
-    selinux_android_set_sehandle(sehandle);
-}
-
-// A C++ wrapper around selabel_lookup() using the cached sehandle.
-// If sehandle is null, this returns success with an empty context.
-bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
-    result->clear();
-
-    if (!sehandle) return true;
-
-    char* context;
-    if (selabel_lookup(sehandle, &context, key.c_str(), type) != 0) {
-        return false;
-    }
-    *result = context;
-    free(context);
-    return true;
-}
-
-// A C++ wrapper around selabel_lookup_best_match() using the cached sehandle.
-// If sehandle is null, this returns success with an empty context.
-bool SelabelLookupFileContextBestMatch(const std::string& key,
-                                       const std::vector<std::string>& aliases, int type,
-                                       std::string* result) {
-    result->clear();
-
-    if (!sehandle) return true;
-
-    std::vector<const char*> c_aliases;
-    for (const auto& alias : aliases) {
-        c_aliases.emplace_back(alias.c_str());
-    }
-    c_aliases.emplace_back(nullptr);
-
-    char* context;
-    if (selabel_lookup_best_match(sehandle, &context, key.c_str(), &c_aliases[0], type) != 0) {
-        return false;
-    }
-    *result = context;
-    free(context);
-    return true;
-}
-
 }  // namespace init
 }  // namespace android
diff --git a/init/selinux.h b/init/selinux.h
index 3aa9406..1a41bfd 100644
--- a/init/selinux.h
+++ b/init/selinux.h
@@ -14,28 +14,27 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_SELINUX_H
-#define _INIT_SELINUX_H
-
-#include <string>
-#include <vector>
+#pragma once
 
 namespace android {
 namespace init {
 
+// Initialize SELinux, then exec init to run in the init SELinux context.
 int SetupSelinux(char** argv);
+
+// Restore the proper security context to files and directories on ramdisk, and
+// those that were created before initial sepolicy load.
+// This must happen before /dev is populated by ueventd.
 void SelinuxRestoreContext();
 
+// Set up SELinux logging to be written to kmsg, to match init's logging.
 void SelinuxSetupKernelLogging();
+
+// Return the Android API level with which the vendor SEPolicy was compiled.
+// Used for version checks such as whether or not vendor_init should be used.
 int SelinuxGetVendorAndroidVersion();
 
-void SelabelInitialize();
-bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
-bool SelabelLookupFileContextBestMatch(const std::string& key,
-                                       const std::vector<std::string>& aliases, int type,
-                                       std::string* result);
+static constexpr char kEnvSelinuxStartedAt[] = "SELINUX_STARTED_AT";
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/service.cpp b/init/service.cpp
index ccc37b7..0e27ff1 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -18,40 +18,33 @@
 
 #include <fcntl.h>
 #include <inttypes.h>
-#include <linux/input.h>
 #include <linux/securebits.h>
 #include <sched.h>
-#include <sys/mount.h>
 #include <sys/prctl.h>
-#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
-#include <sys/wait.h>
 #include <termios.h>
 #include <unistd.h>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <android-base/parseint.h>
 #include <android-base/properties.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <hidl-util/FQName.h>
+#include <cutils/sockets.h>
 #include <processgroup/processgroup.h>
 #include <selinux/selinux.h>
-#include <system/thread_defs.h>
 
-#include "rlimit_parser.h"
+#include "lmkd_service.h"
+#include "service_list.h"
 #include "util.h"
 
 #if defined(__ANDROID__)
+#include <ApexProperties.sysprop.h>
 #include <android/api-level.h>
-#include <sys/system_properties.h>
 
-#include "init.h"
 #include "mount_namespace.h"
-#include "property_service.h"
 #include "selinux.h"
 #else
 #include "host_init_stubs.h"
@@ -60,11 +53,10 @@
 using android::base::boot_clock;
 using android::base::GetProperty;
 using android::base::Join;
-using android::base::ParseInt;
-using android::base::Split;
+using android::base::make_scope_guard;
+using android::base::SetProperty;
 using android::base::StartsWith;
 using android::base::StringPrintf;
-using android::base::unique_fd;
 using android::base::WriteStringToFile;
 
 namespace android {
@@ -106,87 +98,6 @@
     return computed_context;
 }
 
-Result<Success> Service::SetUpMountNamespace() const {
-    constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID;
-
-    // Recursively remount / as slave like zygote does so unmounting and mounting /proc
-    // doesn't interfere with the parent namespace's /proc mount. This will also
-    // prevent any other mounts/unmounts initiated by the service from interfering
-    // with the parent namespace but will still allow mount events from the parent
-    // namespace to propagate to the child.
-    if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
-        return ErrnoError() << "Could not remount(/) recursively as slave";
-    }
-
-    // umount() then mount() /proc and/or /sys
-    // Note that it is not sufficient to mount with MS_REMOUNT.
-    if (namespace_flags_ & CLONE_NEWPID) {
-        if (umount("/proc") == -1) {
-            return ErrnoError() << "Could not umount(/proc)";
-        }
-        if (mount("", "/proc", "proc", kSafeFlags, "") == -1) {
-            return ErrnoError() << "Could not mount(/proc)";
-        }
-    }
-    bool remount_sys = std::any_of(namespaces_to_enter_.begin(), namespaces_to_enter_.end(),
-                                   [](const auto& entry) { return entry.first == CLONE_NEWNET; });
-    if (remount_sys) {
-        if (umount2("/sys", MNT_DETACH) == -1) {
-            return ErrnoError() << "Could not umount(/sys)";
-        }
-        if (mount("", "/sys", "sysfs", kSafeFlags, "") == -1) {
-            return ErrnoError() << "Could not mount(/sys)";
-        }
-    }
-    return Success();
-}
-
-Result<Success> Service::SetUpPidNamespace() const {
-    if (prctl(PR_SET_NAME, name_.c_str()) == -1) {
-        return ErrnoError() << "Could not set name";
-    }
-
-    pid_t child_pid = fork();
-    if (child_pid == -1) {
-        return ErrnoError() << "Could not fork init inside the PID namespace";
-    }
-
-    if (child_pid > 0) {
-        // So that we exit with the right status.
-        static int init_exitstatus = 0;
-        signal(SIGTERM, [](int) { _exit(init_exitstatus); });
-
-        pid_t waited_pid;
-        int status;
-        while ((waited_pid = wait(&status)) > 0) {
-             // This loop will end when there are no processes left inside the
-             // PID namespace or when the init process inside the PID namespace
-             // gets a signal.
-            if (waited_pid == child_pid) {
-                init_exitstatus = status;
-            }
-        }
-        if (!WIFEXITED(init_exitstatus)) {
-            _exit(EXIT_FAILURE);
-        }
-        _exit(WEXITSTATUS(init_exitstatus));
-    }
-    return Success();
-}
-
-Result<Success> Service::EnterNamespaces() const {
-    for (const auto& [nstype, path] : namespaces_to_enter_) {
-        auto fd = unique_fd{open(path.c_str(), O_RDONLY | O_CLOEXEC)};
-        if (fd == -1) {
-            return ErrnoError() << "Could not open namespace at " << path;
-        }
-        if (setns(fd, nstype) == -1) {
-            return ErrnoError() << "Could not setns() namespace at " << path;
-        }
-    }
-    return Success();
-}
-
 static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
     std::vector<std::string> expanded_args;
     std::vector<char*> c_strings;
@@ -194,9 +105,11 @@
     expanded_args.resize(args.size());
     c_strings.push_back(const_cast<char*>(args[0].data()));
     for (std::size_t i = 1; i < args.size(); ++i) {
-        if (!expand_props(args[i], &expanded_args[i])) {
-            LOG(FATAL) << args[0] << ": cannot expand '" << args[i] << "'";
+        auto expanded_arg = ExpandProps(args[i]);
+        if (!expanded_arg) {
+            LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
         }
+        expanded_args[i] = *expanded_arg;
         c_strings.push_back(expanded_args[i].data());
     }
     c_strings.push_back(nullptr);
@@ -208,40 +121,42 @@
     return execv(c_strings[0], c_strings.data()) == 0;
 }
 
-static bool IsRuntimeApexReady() {
+static bool AreRuntimeApexesReady() {
     struct stat buf;
-    return stat("/apex/com.android.runtime/", &buf) == 0;
+    return stat("/apex/com.android.art/", &buf) == 0 &&
+           stat("/apex/com.android.runtime/", &buf) == 0;
 }
 
 unsigned long Service::next_start_order_ = 1;
 bool Service::is_exec_service_running_ = false;
 
 Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
-                 const std::vector<std::string>& args)
-    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
+                 const std::vector<std::string>& args, bool from_apex)
+    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args, from_apex) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::vector<gid_t>& supp_gids, int namespace_flags,
                  const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
-                 const std::vector<std::string>& args)
+                 const std::vector<std::string>& args, bool from_apex)
     : name_(name),
       classnames_({"default"}),
       flags_(flags),
       pid_(0),
       crash_count_(0),
-      uid_(uid),
-      gid_(gid),
-      supp_gids_(supp_gids),
-      namespace_flags_(namespace_flags),
+      proc_attr_{.ioprio_class = IoSchedClass_NONE,
+                 .ioprio_pri = 0,
+                 .uid = uid,
+                 .gid = gid,
+                 .supp_gids = supp_gids,
+                 .priority = 0},
+      namespaces_{.flags = namespace_flags},
       seclabel_(seclabel),
       onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
                  "onrestart", {}),
-      ioprio_class_(IoSchedClass_NONE),
-      ioprio_pri_(0),
-      priority_(0),
-      oom_score_adjust_(-1000),
+      oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
       start_order_(0),
-      args_(args) {}
+      args_(args),
+      from_apex_(from_apex) {}
 
 void Service::NotifyStateChange(const std::string& new_state) const {
     if ((flags_ & SVC_TEMPORARY) != 0) {
@@ -250,18 +165,27 @@
     }
 
     std::string prop_name = "init.svc." + name_;
-    property_set(prop_name, new_state);
+    SetProperty(prop_name, new_state);
 
     if (new_state == "running") {
         uint64_t start_ns = time_started_.time_since_epoch().count();
         std::string boottime_property = "ro.boottime." + name_;
         if (GetProperty(boottime_property, "").empty()) {
-            property_set(boottime_property, std::to_string(start_ns));
+            SetProperty(boottime_property, std::to_string(start_ns));
         }
     }
+
+    // init.svc_debug_pid.* properties are only for tests, and should not be used
+    // on device for security checks.
+    std::string pid_property = "init.svc_debug_pid." + name_;
+    if (new_state == "running") {
+        SetProperty(pid_property, std::to_string(pid_));
+    } else if (new_state == "stopped") {
+        SetProperty(pid_property, "");
+    }
 }
 
-void Service::KillProcessGroup(int signal) {
+void Service::KillProcessGroup(int signal, bool report_oneshot) {
     // If we've already seen a successful result from killProcessGroup*(), then we have removed
     // the cgroup already and calling these functions a second time will simply result in an error.
     // This is true regardless of which signal was sent.
@@ -269,26 +193,33 @@
     if (!process_cgroup_empty_) {
         LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_
                   << ") process group...";
+        int max_processes = 0;
         int r;
         if (signal == SIGTERM) {
-            r = killProcessGroupOnce(uid_, pid_, signal);
+            r = killProcessGroupOnce(proc_attr_.uid, pid_, signal, &max_processes);
         } else {
-            r = killProcessGroup(uid_, pid_, signal);
+            r = killProcessGroup(proc_attr_.uid, pid_, signal, &max_processes);
+        }
+
+        if (report_oneshot && max_processes > 0) {
+            LOG(WARNING)
+                    << "Killed " << max_processes
+                    << " additional processes from a oneshot process group for service '" << name_
+                    << "'. This is new behavior, previously child processes would not be killed in "
+                       "this case.";
         }
 
         if (r == 0) process_cgroup_empty_ = true;
     }
+
+    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
+        LmkdUnregister(name_, pid_);
+    }
 }
 
-void Service::SetProcessAttributes() {
-    for (const auto& rlimit : rlimits_) {
-        if (setrlimit(rlimit.first, &rlimit.second) == -1) {
-            LOG(FATAL) << StringPrintf("setrlimit(%d, {rlim_cur=%ld, rlim_max=%ld}) failed",
-                                       rlimit.first, rlimit.second.rlim_cur, rlimit.second.rlim_max);
-        }
-    }
+void Service::SetProcessAttributesAndCaps() {
     // Keep capabilites on uid change.
-    if (capabilities_ && uid_) {
+    if (capabilities_ && proc_attr_.uid) {
         // If Android is running in a container, some securebits might already
         // be locked, so don't change those.
         unsigned long securebits = prctl(PR_GET_SECUREBITS);
@@ -301,37 +232,21 @@
         }
     }
 
-    // TODO: work out why this fails for `console` then upgrade to FATAL.
-    if (setpgid(0, getpid()) == -1) PLOG(ERROR) << "setpgid failed for " << name_;
+    if (auto result = SetProcessAttributes(proc_attr_); !result) {
+        LOG(FATAL) << "cannot set attribute for " << name_ << ": " << result.error();
+    }
 
-    if (gid_) {
-        if (setgid(gid_) != 0) {
-            PLOG(FATAL) << "setgid failed for " << name_;
-        }
-    }
-    if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) {
-        PLOG(FATAL) << "setgroups failed for " << name_;
-    }
-    if (uid_) {
-        if (setuid(uid_) != 0) {
-            PLOG(FATAL) << "setuid failed for " << name_;
-        }
-    }
     if (!seclabel_.empty()) {
         if (setexeccon(seclabel_.c_str()) < 0) {
             PLOG(FATAL) << "cannot setexeccon('" << seclabel_ << "') for " << name_;
         }
     }
-    if (priority_ != 0) {
-        if (setpriority(PRIO_PROCESS, 0, priority_) != 0) {
-            PLOG(FATAL) << "setpriority failed for " << name_;
-        }
-    }
+
     if (capabilities_) {
         if (!SetCapsForExec(*capabilities_)) {
             LOG(FATAL) << "cannot set capabilities for " << name_;
         }
-    } else if (uid_) {
+    } else if (proc_attr_.uid) {
         // Inheritable caps can be non-zero when running in a container.
         if (!DropInheritableCaps()) {
             LOG(FATAL) << "cannot drop inheritable caps for " << name_;
@@ -341,17 +256,33 @@
 
 void Service::Reap(const siginfo_t& siginfo) {
     if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
-        KillProcessGroup(SIGKILL);
+        KillProcessGroup(SIGKILL, false);
+    } else {
+        // Legacy behavior from ~2007 until Android R: this else branch did not exist and we did not
+        // kill the process group in this case.
+        if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
+            // The new behavior in Android R is to kill these process groups in all cases.  The
+            // 'true' parameter instructions KillProcessGroup() to report a warning message where it
+            // detects a difference in behavior has occurred.
+            KillProcessGroup(SIGKILL, true);
+        }
     }
 
-    // Remove any descriptor resources we may have created.
-    std::for_each(descriptors_.begin(), descriptors_.end(),
-                  std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
+    // Remove any socket resources we may have created.
+    for (const auto& socket : sockets_) {
+        auto path = ANDROID_SOCKET_DIR "/" + socket.name;
+        unlink(path.c_str());
+    }
 
     for (const auto& f : reap_callbacks_) {
         f(siginfo);
     }
 
+    if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) {
+        LOG(ERROR) << "Service with 'reboot_on_failure' option failed, shutting down system.";
+        trigger_shutdown(*on_failure_reboot_target_);
+    }
+
     if (flags_ & SVC_EXEC) UnSetExec();
 
     if (flags_ & SVC_TEMPORARY) return;
@@ -372,10 +303,17 @@
         return;
     }
 
+#if defined(__ANDROID__)
+    static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+#else
+    static bool is_apex_updatable = false;
+#endif
+    const bool is_process_updatable = !pre_apexd_ && is_apex_updatable;
+
     // If we crash > 4 times in 4 minutes or before boot_completed,
     // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
-    if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
+    if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART)) {
         bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
         if (now < time_crashed_ + 4min || !boot_completed) {
             if (++crash_count_ > 4) {
@@ -387,7 +325,8 @@
                     LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
                                << (boot_completed ? "in 4 minutes" : "before boot completed");
                     // Notifies update_verifier and apexd
-                    property_set("ro.init.updatable_crashing", "1");
+                    SetProperty("sys.init.updatable_crashing_process_name", name_);
+                    SetProperty("sys.init.updatable_crashing", "1");
                 }
             }
         } else {
@@ -410,457 +349,22 @@
     LOG(INFO) << "service " << name_;
     LOG(INFO) << "  class '" << Join(classnames_, " ") << "'";
     LOG(INFO) << "  exec " << Join(args_, " ");
-    std::for_each(descriptors_.begin(), descriptors_.end(),
-                  [] (const auto& info) { LOG(INFO) << *info; });
+    for (const auto& socket : sockets_) {
+        LOG(INFO) << "  socket " << socket.name;
+    }
+    for (const auto& file : files_) {
+        LOG(INFO) << "  file " << file.name;
+    }
 }
 
-Result<Success> Service::ParseCapabilities(std::vector<std::string>&& args) {
-    capabilities_ = 0;
 
-    if (!CapAmbientSupported()) {
-        return Error()
-               << "capabilities requested but the kernel does not support ambient capabilities";
-    }
-
-    unsigned int last_valid_cap = GetLastValidCap();
-    if (last_valid_cap >= capabilities_->size()) {
-        LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
-    }
-
-    for (size_t i = 1; i < args.size(); i++) {
-        const std::string& arg = args[i];
-        int res = LookupCap(arg);
-        if (res < 0) {
-            return Error() << StringPrintf("invalid capability '%s'", arg.c_str());
+Result<void> Service::ExecStart() {
+    auto reboot_on_failure = make_scope_guard([this] {
+        if (on_failure_reboot_target_) {
+            trigger_shutdown(*on_failure_reboot_target_);
         }
-        unsigned int cap = static_cast<unsigned int>(res);  // |res| is >= 0.
-        if (cap > last_valid_cap) {
-            return Error() << StringPrintf("capability '%s' not supported by the kernel",
-                                           arg.c_str());
-        }
-        (*capabilities_)[cap] = true;
-    }
-    return Success();
-}
+    });
 
-Result<Success> Service::ParseClass(std::vector<std::string>&& args) {
-    classnames_ = std::set<std::string>(args.begin() + 1, args.end());
-    return Success();
-}
-
-Result<Success> Service::ParseConsole(std::vector<std::string>&& args) {
-    flags_ |= SVC_CONSOLE;
-    console_ = args.size() > 1 ? "/dev/" + args[1] : "";
-    return Success();
-}
-
-Result<Success> Service::ParseCritical(std::vector<std::string>&& args) {
-    flags_ |= SVC_CRITICAL;
-    return Success();
-}
-
-Result<Success> Service::ParseDisabled(std::vector<std::string>&& args) {
-    flags_ |= SVC_DISABLED;
-    flags_ |= SVC_RC_DISABLED;
-    return Success();
-}
-
-Result<Success> Service::ParseEnterNamespace(std::vector<std::string>&& args) {
-    if (args[1] != "net") {
-        return Error() << "Init only supports entering network namespaces";
-    }
-    if (!namespaces_to_enter_.empty()) {
-        return Error() << "Only one network namespace may be entered";
-    }
-    // Network namespaces require that /sys is remounted, otherwise the old adapters will still be
-    // present. Therefore, they also require mount namespaces.
-    namespace_flags_ |= CLONE_NEWNS;
-    namespaces_to_enter_.emplace_back(CLONE_NEWNET, std::move(args[2]));
-    return Success();
-}
-
-Result<Success> Service::ParseGroup(std::vector<std::string>&& args) {
-    auto gid = DecodeUid(args[1]);
-    if (!gid) {
-        return Error() << "Unable to decode GID for '" << args[1] << "': " << gid.error();
-    }
-    gid_ = *gid;
-
-    for (std::size_t n = 2; n < args.size(); n++) {
-        gid = DecodeUid(args[n]);
-        if (!gid) {
-            return Error() << "Unable to decode GID for '" << args[n] << "': " << gid.error();
-        }
-        supp_gids_.emplace_back(*gid);
-    }
-    return Success();
-}
-
-Result<Success> Service::ParsePriority(std::vector<std::string>&& args) {
-    priority_ = 0;
-    if (!ParseInt(args[1], &priority_,
-                  static_cast<int>(ANDROID_PRIORITY_HIGHEST), // highest is negative
-                  static_cast<int>(ANDROID_PRIORITY_LOWEST))) {
-        return Error() << StringPrintf("process priority value must be range %d - %d",
-                                       ANDROID_PRIORITY_HIGHEST, ANDROID_PRIORITY_LOWEST);
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseInterface(std::vector<std::string>&& args) {
-    const std::string& interface_name = args[1];
-    const std::string& instance_name = args[2];
-
-    FQName fq_name;
-    if (!FQName::parse(interface_name, &fq_name)) {
-        return Error() << "Invalid fully-qualified name for interface '" << interface_name << "'";
-    }
-
-    if (!fq_name.isFullyQualified()) {
-        return Error() << "Interface name not fully-qualified '" << interface_name << "'";
-    }
-
-    if (fq_name.isValidValueName()) {
-        return Error() << "Interface name must not be a value name '" << interface_name << "'";
-    }
-
-    const std::string fullname = interface_name + "/" + instance_name;
-
-    for (const auto& svc : ServiceList::GetInstance()) {
-        if (svc->interfaces().count(fullname) > 0) {
-            return Error() << "Interface '" << fullname << "' redefined in " << name()
-                           << " but is already defined by " << svc->name();
-        }
-    }
-
-    interfaces_.insert(fullname);
-
-    return Success();
-}
-
-Result<Success> Service::ParseIoprio(std::vector<std::string>&& args) {
-    if (!ParseInt(args[2], &ioprio_pri_, 0, 7)) {
-        return Error() << "priority value must be range 0 - 7";
-    }
-
-    if (args[1] == "rt") {
-        ioprio_class_ = IoSchedClass_RT;
-    } else if (args[1] == "be") {
-        ioprio_class_ = IoSchedClass_BE;
-    } else if (args[1] == "idle") {
-        ioprio_class_ = IoSchedClass_IDLE;
-    } else {
-        return Error() << "ioprio option usage: ioprio <rt|be|idle> <0-7>";
-    }
-
-    return Success();
-}
-
-Result<Success> Service::ParseKeycodes(std::vector<std::string>&& args) {
-    auto it = args.begin() + 1;
-    if (args.size() == 2 && StartsWith(args[1], "$")) {
-        std::string expanded;
-        if (!expand_props(args[1], &expanded)) {
-            return Error() << "Could not expand property '" << args[1] << "'";
-        }
-
-        // If the property is not set, it defaults to none, in which case there are no keycodes
-        // for this service.
-        if (expanded == "none") {
-            return Success();
-        }
-
-        args = Split(expanded, ",");
-        it = args.begin();
-    }
-
-    for (; it != args.end(); ++it) {
-        int code;
-        if (ParseInt(*it, &code, 0, KEY_MAX)) {
-            for (auto& key : keycodes_) {
-                if (key == code) return Error() << "duplicate keycode: " << *it;
-            }
-            keycodes_.insert(std::upper_bound(keycodes_.begin(), keycodes_.end(), code), code);
-        } else {
-            return Error() << "invalid keycode: " << *it;
-        }
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseOneshot(std::vector<std::string>&& args) {
-    flags_ |= SVC_ONESHOT;
-    return Success();
-}
-
-Result<Success> Service::ParseOnrestart(std::vector<std::string>&& args) {
-    args.erase(args.begin());
-    int line = onrestart_.NumCommands() + 1;
-    if (auto result = onrestart_.AddCommand(std::move(args), line); !result) {
-        return Error() << "cannot add Onrestart command: " << result.error();
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseNamespace(std::vector<std::string>&& args) {
-    for (size_t i = 1; i < args.size(); i++) {
-        if (args[i] == "pid") {
-            namespace_flags_ |= CLONE_NEWPID;
-            // PID namespaces require mount namespaces.
-            namespace_flags_ |= CLONE_NEWNS;
-        } else if (args[i] == "mnt") {
-            namespace_flags_ |= CLONE_NEWNS;
-        } else {
-            return Error() << "namespace must be 'pid' or 'mnt'";
-        }
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseOomScoreAdjust(std::vector<std::string>&& args) {
-    if (!ParseInt(args[1], &oom_score_adjust_, -1000, 1000)) {
-        return Error() << "oom_score_adjust value must be in range -1000 - +1000";
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseOverride(std::vector<std::string>&& args) {
-    override_ = true;
-    return Success();
-}
-
-Result<Success> Service::ParseMemcgSwappiness(std::vector<std::string>&& args) {
-    if (!ParseInt(args[1], &swappiness_, 0)) {
-        return Error() << "swappiness value must be equal or greater than 0";
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseMemcgLimitInBytes(std::vector<std::string>&& args) {
-    if (!ParseInt(args[1], &limit_in_bytes_, 0)) {
-        return Error() << "limit_in_bytes value must be equal or greater than 0";
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseMemcgLimitPercent(std::vector<std::string>&& args) {
-    if (!ParseInt(args[1], &limit_percent_, 0)) {
-        return Error() << "limit_percent value must be equal or greater than 0";
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseMemcgLimitProperty(std::vector<std::string>&& args) {
-    limit_property_ = std::move(args[1]);
-    return Success();
-}
-
-Result<Success> Service::ParseMemcgSoftLimitInBytes(std::vector<std::string>&& args) {
-    if (!ParseInt(args[1], &soft_limit_in_bytes_, 0)) {
-        return Error() << "soft_limit_in_bytes value must be equal or greater than 0";
-    }
-    return Success();
-}
-
-Result<Success> Service::ParseProcessRlimit(std::vector<std::string>&& args) {
-    auto rlimit = ParseRlimit(args);
-    if (!rlimit) return rlimit.error();
-
-    rlimits_.emplace_back(*rlimit);
-    return Success();
-}
-
-Result<Success> Service::ParseRestartPeriod(std::vector<std::string>&& args) {
-    int period;
-    if (!ParseInt(args[1], &period, 5)) {
-        return Error() << "restart_period value must be an integer >= 5";
-    }
-    restart_period_ = std::chrono::seconds(period);
-    return Success();
-}
-
-Result<Success> Service::ParseSeclabel(std::vector<std::string>&& args) {
-    seclabel_ = std::move(args[1]);
-    return Success();
-}
-
-Result<Success> Service::ParseSigstop(std::vector<std::string>&& args) {
-    sigstop_ = true;
-    return Success();
-}
-
-Result<Success> Service::ParseSetenv(std::vector<std::string>&& args) {
-    environment_vars_.emplace_back(std::move(args[1]), std::move(args[2]));
-    return Success();
-}
-
-Result<Success> Service::ParseShutdown(std::vector<std::string>&& args) {
-    if (args[1] == "critical") {
-        flags_ |= SVC_SHUTDOWN_CRITICAL;
-        return Success();
-    }
-    return Error() << "Invalid shutdown option";
-}
-
-Result<Success> Service::ParseTimeoutPeriod(std::vector<std::string>&& args) {
-    int period;
-    if (!ParseInt(args[1], &period, 1)) {
-        return Error() << "timeout_period value must be an integer >= 1";
-    }
-    timeout_period_ = std::chrono::seconds(period);
-    return Success();
-}
-
-template <typename T>
-Result<Success> Service::AddDescriptor(std::vector<std::string>&& args) {
-    int perm = args.size() > 3 ? std::strtoul(args[3].c_str(), 0, 8) : -1;
-    Result<uid_t> uid = 0;
-    Result<gid_t> gid = 0;
-    std::string context = args.size() > 6 ? args[6] : "";
-
-    if (args.size() > 4) {
-        uid = DecodeUid(args[4]);
-        if (!uid) {
-            return Error() << "Unable to find UID for '" << args[4] << "': " << uid.error();
-        }
-    }
-
-    if (args.size() > 5) {
-        gid = DecodeUid(args[5]);
-        if (!gid) {
-            return Error() << "Unable to find GID for '" << args[5] << "': " << gid.error();
-        }
-    }
-
-    auto descriptor = std::make_unique<T>(args[1], args[2], *uid, *gid, perm, context);
-
-    auto old =
-        std::find_if(descriptors_.begin(), descriptors_.end(),
-                     [&descriptor] (const auto& other) { return descriptor.get() == other.get(); });
-
-    if (old != descriptors_.end()) {
-        return Error() << "duplicate descriptor " << args[1] << " " << args[2];
-    }
-
-    descriptors_.emplace_back(std::move(descriptor));
-    return Success();
-}
-
-// name type perm [ uid gid context ]
-Result<Success> Service::ParseSocket(std::vector<std::string>&& args) {
-    if (!StartsWith(args[2], "dgram") && !StartsWith(args[2], "stream") &&
-        !StartsWith(args[2], "seqpacket")) {
-        return Error() << "socket type must be 'dgram', 'stream' or 'seqpacket'";
-    }
-    return AddDescriptor<SocketInfo>(std::move(args));
-}
-
-// name type perm [ uid gid context ]
-Result<Success> Service::ParseFile(std::vector<std::string>&& args) {
-    if (args[2] != "r" && args[2] != "w" && args[2] != "rw") {
-        return Error() << "file type must be 'r', 'w' or 'rw'";
-    }
-    std::string expanded;
-    if (!expand_props(args[1], &expanded)) {
-        return Error() << "Could not expand property in file path '" << args[1] << "'";
-    }
-    args[1] = std::move(expanded);
-    if ((args[1][0] != '/') || (args[1].find("../") != std::string::npos)) {
-        return Error() << "file name must not be relative";
-    }
-    return AddDescriptor<FileInfo>(std::move(args));
-}
-
-Result<Success> Service::ParseUser(std::vector<std::string>&& args) {
-    auto uid = DecodeUid(args[1]);
-    if (!uid) {
-        return Error() << "Unable to find UID for '" << args[1] << "': " << uid.error();
-    }
-    uid_ = *uid;
-    return Success();
-}
-
-Result<Success> Service::ParseWritepid(std::vector<std::string>&& args) {
-    args.erase(args.begin());
-    writepid_files_ = std::move(args);
-    return Success();
-}
-
-Result<Success> Service::ParseUpdatable(std::vector<std::string>&& args) {
-    updatable_ = true;
-    return Success();
-}
-
-class Service::OptionParserMap : public KeywordMap<OptionParser> {
-  public:
-    OptionParserMap() {}
-
-  private:
-    const Map& map() const override;
-};
-
-const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
-    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
-    // clang-format off
-    static const Map option_parsers = {
-        {"capabilities",
-                        {0,     kMax, &Service::ParseCapabilities}},
-        {"class",       {1,     kMax, &Service::ParseClass}},
-        {"console",     {0,     1,    &Service::ParseConsole}},
-        {"critical",    {0,     0,    &Service::ParseCritical}},
-        {"disabled",    {0,     0,    &Service::ParseDisabled}},
-        {"enter_namespace",
-                        {2,     2,    &Service::ParseEnterNamespace}},
-        {"file",        {2,     2,    &Service::ParseFile}},
-        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},
-        {"interface",   {2,     2,    &Service::ParseInterface}},
-        {"ioprio",      {2,     2,    &Service::ParseIoprio}},
-        {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
-        {"memcg.limit_in_bytes",
-                        {1,     1,    &Service::ParseMemcgLimitInBytes}},
-        {"memcg.limit_percent",
-                        {1,     1,    &Service::ParseMemcgLimitPercent}},
-        {"memcg.limit_property",
-                        {1,     1,    &Service::ParseMemcgLimitProperty}},
-        {"memcg.soft_limit_in_bytes",
-                        {1,     1,    &Service::ParseMemcgSoftLimitInBytes}},
-        {"memcg.swappiness",
-                        {1,     1,    &Service::ParseMemcgSwappiness}},
-        {"namespace",   {1,     2,    &Service::ParseNamespace}},
-        {"oneshot",     {0,     0,    &Service::ParseOneshot}},
-        {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
-        {"oom_score_adjust",
-                        {1,     1,    &Service::ParseOomScoreAdjust}},
-        {"override",    {0,     0,    &Service::ParseOverride}},
-        {"priority",    {1,     1,    &Service::ParsePriority}},
-        {"restart_period",
-                        {1,     1,    &Service::ParseRestartPeriod}},
-        {"rlimit",      {3,     3,    &Service::ParseProcessRlimit}},
-        {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
-        {"setenv",      {2,     2,    &Service::ParseSetenv}},
-        {"shutdown",    {1,     1,    &Service::ParseShutdown}},
-        {"sigstop",     {0,     0,    &Service::ParseSigstop}},
-        {"socket",      {3,     6,    &Service::ParseSocket}},
-        {"timeout_period",
-                        {1,     1,    &Service::ParseTimeoutPeriod}},
-        {"updatable",   {0,     0,    &Service::ParseUpdatable}},
-        {"user",        {1,     1,    &Service::ParseUser}},
-        {"writepid",    {1,     kMax, &Service::ParseWritepid}},
-    };
-    // clang-format on
-    return option_parsers;
-}
-
-Result<Success> Service::ParseLine(std::vector<std::string>&& args) {
-    static const OptionParserMap parser_map;
-    auto parser = parser_map.FindFunction(args);
-
-    if (!parser) return parser.error();
-
-    return std::invoke(*parser, this, std::move(args));
-}
-
-Result<Success> Service::ExecStart() {
     if (is_updatable() && !ServiceList::GetInstance().IsServicesUpdated()) {
         // Don't delay the service for ExecStart() as the semantic is that
         // the caller might depend on the side effect of the execution.
@@ -877,14 +381,21 @@
     flags_ |= SVC_EXEC;
     is_exec_service_running_ = true;
 
-    LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << uid_ << " gid "
-              << gid_ << "+" << supp_gids_.size() << " context "
+    LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << proc_attr_.uid
+              << " gid " << proc_attr_.gid << "+" << proc_attr_.supp_gids.size() << " context "
               << (!seclabel_.empty() ? seclabel_ : "default") << ") started; waiting...";
 
-    return Success();
+    reboot_on_failure.Disable();
+    return {};
 }
 
-Result<Success> Service::Start() {
+Result<void> Service::Start() {
+    auto reboot_on_failure = make_scope_guard([this] {
+        if (on_failure_reboot_target_) {
+            trigger_shutdown(*on_failure_reboot_target_);
+        }
+    });
+
     if (is_updatable() && !ServiceList::GetInstance().IsServicesUpdated()) {
         ServiceList::GetInstance().DelayService(*this);
         return Error() << "Cannot start an updatable service '" << name_
@@ -907,21 +418,22 @@
             flags_ |= SVC_RESTART;
         }
         // It is not an error to try to start a service that is already running.
-        return Success();
+        reboot_on_failure.Disable();
+        return {};
     }
 
     bool needs_console = (flags_ & SVC_CONSOLE);
     if (needs_console) {
-        if (console_.empty()) {
-            console_ = default_console;
+        if (proc_attr_.console.empty()) {
+            proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console");
         }
 
         // Make sure that open call succeeds to ensure a console driver is
         // properly registered for the device node
-        int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
+        int console_fd = open(proc_attr_.console.c_str(), O_RDWR | O_CLOEXEC);
         if (console_fd < 0) {
             flags_ |= SVC_DISABLED;
-            return ErrnoError() << "Couldn't open console '" << console_ << "'";
+            return ErrnoError() << "Couldn't open console '" << proc_attr_.console << "'";
         }
         close(console_fd);
     }
@@ -943,11 +455,11 @@
         scon = *result;
     }
 
-    if (!IsRuntimeApexReady() && !pre_apexd_) {
-        // If this service is started before the runtime APEX gets available,
-        // mark it as pre-apexd one. Note that this marking is permanent. So
-        // for example, if the service is re-launched (e.g., due to crash),
-        // it is still recognized as pre-apexd... for consistency.
+    if (!AreRuntimeApexesReady() && !pre_apexd_) {
+        // If this service is started before the Runtime and ART APEXes get
+        // available, mark it as pre-apexd one. Note that this marking is
+        // permanent. So for example, if the service is re-launched (e.g., due
+        // to crash), it is still recognized as pre-apexd... for consistency.
         pre_apexd_ = true;
     }
 
@@ -955,9 +467,26 @@
 
     LOG(INFO) << "starting service '" << name_ << "'...";
 
+    std::vector<Descriptor> descriptors;
+    for (const auto& socket : sockets_) {
+        if (auto result = socket.Create(scon)) {
+            descriptors.emplace_back(std::move(*result));
+        } else {
+            LOG(INFO) << "Could not create socket '" << socket.name << "': " << result.error();
+        }
+    }
+
+    for (const auto& file : files_) {
+        if (auto result = file.Create()) {
+            descriptors.emplace_back(std::move(*result));
+        } else {
+            LOG(INFO) << "Could not open file '" << file.name << "': " << result.error();
+        }
+    }
+
     pid_t pid = -1;
-    if (namespace_flags_) {
-        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
+    if (namespaces_.flags) {
+        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
     } else {
         pid = fork();
     }
@@ -965,97 +494,30 @@
     if (pid == 0) {
         umask(077);
 
-        if (auto result = EnterNamespaces(); !result) {
-            LOG(FATAL) << "Service '" << name_ << "' could not enter namespaces: " << result.error();
-        }
-
-#if defined(__ANDROID__)
-        if (pre_apexd_) {
-            if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
-                LOG(FATAL) << "Service '" << name_ << "' could not enter "
-                           << "into the bootstrap mount namespace";
-            }
-        }
-#endif
-
-        if (namespace_flags_ & CLONE_NEWNS) {
-            if (auto result = SetUpMountNamespace(); !result) {
-                LOG(FATAL) << "Service '" << name_
-                           << "' could not set up mount namespace: " << result.error();
-            }
-        }
-
-        if (namespace_flags_ & CLONE_NEWPID) {
-            // This will fork again to run an init process inside the PID
-            // namespace.
-            if (auto result = SetUpPidNamespace(); !result) {
-                LOG(FATAL) << "Service '" << name_
-                           << "' could not set up PID namespace: " << result.error();
-            }
+        if (auto result = EnterNamespaces(namespaces_, name_, pre_apexd_); !result) {
+            LOG(FATAL) << "Service '" << name_
+                       << "' failed to set up namespaces: " << result.error();
         }
 
         for (const auto& [key, value] : environment_vars_) {
             setenv(key.c_str(), value.c_str(), 1);
         }
 
-        std::for_each(descriptors_.begin(), descriptors_.end(),
-                      std::bind(&DescriptorInfo::CreateAndPublish, std::placeholders::_1, scon));
-
-        // See if there were "writepid" instructions to write to files under cpuset path.
-        std::string cpuset_path;
-        if (CgroupGetControllerPath("cpuset", &cpuset_path)) {
-            auto cpuset_predicate = [&cpuset_path](const std::string& path) {
-                return StartsWith(path, cpuset_path + "/");
-            };
-            auto iter =
-                    std::find_if(writepid_files_.begin(), writepid_files_.end(), cpuset_predicate);
-            if (iter == writepid_files_.end()) {
-                // There were no "writepid" instructions for cpusets, check if the system default
-                // cpuset is specified to be used for the process.
-                std::string default_cpuset = GetProperty("ro.cpuset.default", "");
-                if (!default_cpuset.empty()) {
-                    // Make sure the cpuset name starts and ends with '/'.
-                    // A single '/' means the 'root' cpuset.
-                    if (default_cpuset.front() != '/') {
-                        default_cpuset.insert(0, 1, '/');
-                    }
-                    if (default_cpuset.back() != '/') {
-                        default_cpuset.push_back('/');
-                    }
-                    writepid_files_.push_back(
-                            StringPrintf("%s%stasks", cpuset_path.c_str(), default_cpuset.c_str()));
-                }
-            }
-        } else {
-            LOG(ERROR) << "cpuset cgroup controller is not mounted!";
-        }
-        std::string pid_str = std::to_string(getpid());
-        for (const auto& file : writepid_files_) {
-            if (!WriteStringToFile(pid_str, file)) {
-                PLOG(ERROR) << "couldn't write " << pid_str << " to " << file;
-            }
+        for (const auto& descriptor : descriptors) {
+            descriptor.Publish();
         }
 
-        if (ioprio_class_ != IoSchedClass_NONE) {
-            if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) {
-                PLOG(ERROR) << "failed to set pid " << getpid()
-                            << " ioprio=" << ioprio_class_ << "," << ioprio_pri_;
-            }
-        }
-
-        if (needs_console) {
-            setsid();
-            OpenConsole();
-        } else {
-            ZapStdio();
+        if (auto result = WritePidToFiles(&writepid_files_); !result) {
+            LOG(ERROR) << "failed to write pid to files: " << result.error();
         }
 
         // As requested, set our gid, supplemental gids, uid, context, and
         // priority. Aborts on failure.
-        SetProcessAttributes();
+        SetProcessAttributesAndCaps();
 
         if (!ExpandArgsAndExecv(args_, sigstop_)) {
-            PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
+            PLOG(ERROR) << "cannot execv('" << args_[0]
+                        << "'). See the 'Debugging init' section of init's README.md for tips";
         }
 
         _exit(127);
@@ -1066,7 +528,7 @@
         return ErrnoError() << "Failed to fork";
     }
 
-    if (oom_score_adjust_ != -1000) {
+    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
         std::string oom_str = std::to_string(oom_score_adjust_);
         std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
         if (!WriteStringToFile(oom_str, oom_file)) {
@@ -1082,19 +544,19 @@
 
     bool use_memcg = swappiness_ != -1 || soft_limit_in_bytes_ != -1 || limit_in_bytes_ != -1 ||
                       limit_percent_ != -1 || !limit_property_.empty();
-    errno = -createProcessGroup(uid_, pid_, use_memcg);
+    errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
     if (errno != 0) {
-        PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '"
-                    << name_ << "'";
+        PLOG(ERROR) << "createProcessGroup(" << proc_attr_.uid << ", " << pid_
+                    << ") failed for service '" << name_ << "'";
     } else if (use_memcg) {
         if (swappiness_ != -1) {
-            if (!setProcessGroupSwappiness(uid_, pid_, swappiness_)) {
+            if (!setProcessGroupSwappiness(proc_attr_.uid, pid_, swappiness_)) {
                 PLOG(ERROR) << "setProcessGroupSwappiness failed";
             }
         }
 
         if (soft_limit_in_bytes_ != -1) {
-            if (!setProcessGroupSoftLimit(uid_, pid_, soft_limit_in_bytes_)) {
+            if (!setProcessGroupSoftLimit(proc_attr_.uid, pid_, soft_limit_in_bytes_)) {
                 PLOG(ERROR) << "setProcessGroupSoftLimit failed";
             }
         }
@@ -1121,31 +583,36 @@
         }
 
         if (computed_limit_in_bytes != size_t(-1)) {
-            if (!setProcessGroupLimit(uid_, pid_, computed_limit_in_bytes)) {
+            if (!setProcessGroupLimit(proc_attr_.uid, pid_, computed_limit_in_bytes)) {
                 PLOG(ERROR) << "setProcessGroupLimit failed";
             }
         }
     }
 
+    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
+        LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
+    }
+
     NotifyStateChange("running");
-    return Success();
+    reboot_on_failure.Disable();
+    return {};
 }
 
-Result<Success> Service::StartIfNotDisabled() {
+Result<void> Service::StartIfNotDisabled() {
     if (!(flags_ & SVC_DISABLED)) {
         return Start();
     } else {
         flags_ |= SVC_DISABLED_START;
     }
-    return Success();
+    return {};
 }
 
-Result<Success> Service::Enable() {
+Result<void> Service::Enable() {
     flags_ &= ~(SVC_DISABLED | SVC_RC_DISABLED);
     if (flags_ & SVC_DISABLED_START) {
         return Start();
     }
-    return Success();
+    return {};
 }
 
 void Service::Reset() {
@@ -1161,14 +628,14 @@
     }
 }
 
-Result<Success> Service::StartIfPostData() {
+Result<void> Service::StartIfPostData() {
     // Start the service, but only if it was started after /data was mounted,
     // and it was still running when we reset the post-data services.
     if (running_at_post_data_reset_) {
         return Start();
     }
 
-    return Success();
+    return {};
 }
 
 void Service::Stop() {
@@ -1241,37 +708,8 @@
     }
 }
 
-void Service::ZapStdio() const {
-    int fd;
-    fd = open("/dev/null", O_RDWR);
-    dup2(fd, 0);
-    dup2(fd, 1);
-    dup2(fd, 2);
-    close(fd);
-}
-
-void Service::OpenConsole() const {
-    int fd = open(console_.c_str(), O_RDWR);
-    if (fd == -1) fd = open("/dev/null", O_RDWR);
-    ioctl(fd, TIOCSCTTY, 0);
-    dup2(fd, 0);
-    dup2(fd, 1);
-    dup2(fd, 2);
-    close(fd);
-}
-
-ServiceList::ServiceList() {}
-
-ServiceList& ServiceList::GetInstance() {
-    static ServiceList instance;
-    return instance;
-}
-
-void ServiceList::AddService(std::unique_ptr<Service> service) {
-    services_.emplace_back(std::move(service));
-}
-
-std::unique_ptr<Service> Service::MakeTemporaryOneshotService(const std::vector<std::string>& args) {
+Result<std::unique_ptr<Service>> Service::MakeTemporaryOneshotService(
+        const std::vector<std::string>& args) {
     // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS...
     // SECLABEL can be a - to denote default
     std::size_t command_arg = 1;
@@ -1282,13 +720,11 @@
         }
     }
     if (command_arg > 4 + NR_SVC_SUPP_GIDS) {
-        LOG(ERROR) << "exec called with too many supplementary group ids";
-        return nullptr;
+        return Error() << "exec called with too many supplementary group ids";
     }
 
     if (command_arg >= args.size()) {
-        LOG(ERROR) << "exec called without command";
-        return nullptr;
+        return Error() << "exec called without command";
     }
     std::vector<std::string> str_args(args.begin() + command_arg, args.end());
 
@@ -1307,8 +743,7 @@
     if (command_arg > 3) {
         uid = DecodeUid(args[2]);
         if (!uid) {
-            LOG(ERROR) << "Unable to decode UID for '" << args[2] << "': " << uid.error();
-            return nullptr;
+            return Error() << "Unable to decode UID for '" << args[2] << "': " << uid.error();
         }
     }
     Result<gid_t> gid = 0;
@@ -1316,157 +751,21 @@
     if (command_arg > 4) {
         gid = DecodeUid(args[3]);
         if (!gid) {
-            LOG(ERROR) << "Unable to decode GID for '" << args[3] << "': " << gid.error();
-            return nullptr;
+            return Error() << "Unable to decode GID for '" << args[3] << "': " << gid.error();
         }
         std::size_t nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */;
         for (size_t i = 0; i < nr_supp_gids; ++i) {
             auto supp_gid = DecodeUid(args[4 + i]);
             if (!supp_gid) {
-                LOG(ERROR) << "Unable to decode GID for '" << args[4 + i]
-                           << "': " << supp_gid.error();
-                return nullptr;
+                return Error() << "Unable to decode GID for '" << args[4 + i]
+                               << "': " << supp_gid.error();
             }
             supp_gids.push_back(*supp_gid);
         }
     }
 
     return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
-                                     nullptr, str_args);
-}
-
-// Shutdown services in the opposite order that they were started.
-const std::vector<Service*> ServiceList::services_in_shutdown_order() const {
-    std::vector<Service*> shutdown_services;
-    for (const auto& service : services_) {
-        if (service->start_order() > 0) shutdown_services.emplace_back(service.get());
-    }
-    std::sort(shutdown_services.begin(), shutdown_services.end(),
-              [](const auto& a, const auto& b) { return a->start_order() > b->start_order(); });
-    return shutdown_services;
-}
-
-void ServiceList::RemoveService(const Service& svc) {
-    auto svc_it = std::find_if(services_.begin(), services_.end(),
-                               [&svc] (const std::unique_ptr<Service>& s) {
-                                   return svc.name() == s->name();
-                               });
-    if (svc_it == services_.end()) {
-        return;
-    }
-
-    services_.erase(svc_it);
-}
-
-void ServiceList::DumpState() const {
-    for (const auto& s : services_) {
-        s->DumpState();
-    }
-}
-
-void ServiceList::MarkPostData() {
-    post_data_ = true;
-}
-
-bool ServiceList::IsPostData() {
-    return post_data_;
-}
-
-void ServiceList::MarkServicesUpdate() {
-    services_update_finished_ = true;
-
-    // start the delayed services
-    for (const auto& name : delayed_service_names_) {
-        Service* service = FindService(name);
-        if (service == nullptr) {
-            LOG(ERROR) << "delayed service '" << name << "' could not be found.";
-            continue;
-        }
-        if (auto result = service->Start(); !result) {
-            LOG(ERROR) << result.error_string();
-        }
-    }
-    delayed_service_names_.clear();
-}
-
-void ServiceList::DelayService(const Service& service) {
-    if (services_update_finished_) {
-        LOG(ERROR) << "Cannot delay the start of service '" << service.name()
-                   << "' because all services are already updated. Ignoring.";
-        return;
-    }
-    delayed_service_names_.emplace_back(service.name());
-}
-
-Result<Success> ServiceParser::ParseSection(std::vector<std::string>&& args,
-                                            const std::string& filename, int line) {
-    if (args.size() < 3) {
-        return Error() << "services must have a name and a program";
-    }
-
-    const std::string& name = args[1];
-    if (!IsValidName(name)) {
-        return Error() << "invalid service name '" << name << "'";
-    }
-
-    filename_ = filename;
-
-    Subcontext* restart_action_subcontext = nullptr;
-    if (subcontexts_) {
-        for (auto& subcontext : *subcontexts_) {
-            if (StartsWith(filename, subcontext.path_prefix())) {
-                restart_action_subcontext = &subcontext;
-                break;
-            }
-        }
-    }
-
-    std::vector<std::string> str_args(args.begin() + 2, args.end());
-
-    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
-        if (str_args[0] == "/sbin/watchdogd") {
-            str_args[0] = "/system/bin/watchdogd";
-        }
-    }
-
-    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
-    return Success();
-}
-
-Result<Success> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
-    return service_ ? service_->ParseLine(std::move(args)) : Success();
-}
-
-Result<Success> ServiceParser::EndSection() {
-    if (service_) {
-        Service* old_service = service_list_->FindService(service_->name());
-        if (old_service) {
-            if (!service_->is_override()) {
-                return Error() << "ignored duplicate definition of service '" << service_->name()
-                               << "'";
-            }
-
-            if (StartsWith(filename_, "/apex/") && !old_service->is_updatable()) {
-                return Error() << "cannot update a non-updatable service '" << service_->name()
-                               << "' with a config in APEX";
-            }
-
-            service_list_->RemoveService(*old_service);
-            old_service = nullptr;
-        }
-
-        service_list_->AddService(std::move(service_));
-    }
-
-    return Success();
-}
-
-bool ServiceParser::IsValidName(const std::string& name) const {
-    // Property names can be any length, but may only contain certain characters.
-    // Property values can contain any characters, but may only be a certain length.
-    // (The latter restriction is needed because `start` and `stop` work by writing
-    // the service name to the "ctl.start" and "ctl.stop" properties.)
-    return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
+                                     nullptr, str_args, false);
 }
 
 }  // namespace init
diff --git a/init/service.h b/init/service.h
index ae29f28..cf3f0c2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_SERVICE_H
-#define _INIT_SERVICE_H
+#pragma once
 
 #include <signal.h>
-#include <sys/resource.h>
 #include <sys/types.h>
 
 #include <chrono>
@@ -33,9 +31,9 @@
 
 #include "action.h"
 #include "capabilities.h"
-#include "descriptors.h"
 #include "keyword_map.h"
 #include "parser.h"
+#include "service_utils.h"
 #include "subcontext.h"
 
 #define SVC_DISABLED 0x001        // do not autostart with class
@@ -63,24 +61,27 @@
 namespace init {
 
 class Service {
+    friend class ServiceParser;
+
   public:
     Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
-            const std::vector<std::string>& args);
+            const std::vector<std::string>& args, bool from_apex = false);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
-            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
-            const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
+            const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
+            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args,
+            bool from_apex = false);
+
+    static Result<std::unique_ptr<Service>> MakeTemporaryOneshotService(
             const std::vector<std::string>& args);
 
-    static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
-
     bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
-    Result<Success> ParseLine(std::vector<std::string>&& args);
-    Result<Success> ExecStart();
-    Result<Success> Start();
-    Result<Success> StartIfNotDisabled();
-    Result<Success> StartIfPostData();
-    Result<Success> Enable();
+    bool IsEnabled() { return (flags_ & SVC_DISABLED) == 0; }
+    Result<void> ExecStart();
+    Result<void> Start();
+    Result<void> StartIfNotDisabled();
+    Result<void> StartIfPostData();
+    Result<void> Enable();
     void Reset();
     void ResetIfPostData();
     void Stop();
@@ -98,6 +99,7 @@
     void AddReapCallback(std::function<void(const siginfo_t& siginfo)> callback) {
         reap_callbacks_.emplace_back(std::move(callback));
     }
+    size_t CheckAllCommands() const { return onrestart_.CheckAllCommands(); }
 
     static bool is_exec_service_running() { return is_exec_service_running_; }
 
@@ -107,16 +109,16 @@
     pid_t pid() const { return pid_; }
     android::base::boot_clock::time_point time_started() const { return time_started_; }
     int crash_count() const { return crash_count_; }
-    uid_t uid() const { return uid_; }
-    gid_t gid() const { return gid_; }
-    unsigned namespace_flags() const { return namespace_flags_; }
-    const std::vector<gid_t>& supp_gids() const { return supp_gids_; }
+    uid_t uid() const { return proc_attr_.uid; }
+    gid_t gid() const { return proc_attr_.gid; }
+    int namespace_flags() const { return namespaces_.flags; }
+    const std::vector<gid_t>& supp_gids() const { return proc_attr_.supp_gids; }
     const std::string& seclabel() const { return seclabel_; }
     const std::vector<int>& keycodes() const { return keycodes_; }
-    IoSchedClass ioprio_class() const { return ioprio_class_; }
-    int ioprio_pri() const { return ioprio_pri_; }
+    IoSchedClass ioprio_class() const { return proc_attr_.ioprio_class; }
+    int ioprio_pri() const { return proc_attr_.ioprio_pri; }
     const std::set<std::string>& interfaces() const { return interfaces_; }
-    int priority() const { return priority_; }
+    int priority() const { return proc_attr_.priority; }
     int oom_score_adjust() const { return oom_score_adjust_; }
     bool is_override() const { return override_; }
     bool process_cgroup_empty() const { return process_cgroup_empty_; }
@@ -127,64 +129,19 @@
     const std::vector<std::string>& args() const { return args_; }
     bool is_updatable() const { return updatable_; }
     bool is_post_data() const { return post_data_; }
+    bool is_from_apex() const { return from_apex_; }
 
   private:
-    using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
-    class OptionParserMap;
-
-    Result<Success> SetUpMountNamespace() const;
-    Result<Success> SetUpPidNamespace() const;
-    Result<Success> EnterNamespaces() const;
     void NotifyStateChange(const std::string& new_state) const;
     void StopOrReset(int how);
-    void ZapStdio() const;
-    void OpenConsole() const;
-    void KillProcessGroup(int signal);
-    void SetProcessAttributes();
-
-    Result<Success> ParseCapabilities(std::vector<std::string>&& args);
-    Result<Success> ParseClass(std::vector<std::string>&& args);
-    Result<Success> ParseConsole(std::vector<std::string>&& args);
-    Result<Success> ParseCritical(std::vector<std::string>&& args);
-    Result<Success> ParseDisabled(std::vector<std::string>&& args);
-    Result<Success> ParseEnterNamespace(std::vector<std::string>&& args);
-    Result<Success> ParseGroup(std::vector<std::string>&& args);
-    Result<Success> ParsePriority(std::vector<std::string>&& args);
-    Result<Success> ParseInterface(std::vector<std::string>&& args);
-    Result<Success> ParseIoprio(std::vector<std::string>&& args);
-    Result<Success> ParseKeycodes(std::vector<std::string>&& args);
-    Result<Success> ParseOneshot(std::vector<std::string>&& args);
-    Result<Success> ParseOnrestart(std::vector<std::string>&& args);
-    Result<Success> ParseOomScoreAdjust(std::vector<std::string>&& args);
-    Result<Success> ParseOverride(std::vector<std::string>&& args);
-    Result<Success> ParseMemcgLimitInBytes(std::vector<std::string>&& args);
-    Result<Success> ParseMemcgLimitPercent(std::vector<std::string>&& args);
-    Result<Success> ParseMemcgLimitProperty(std::vector<std::string>&& args);
-    Result<Success> ParseMemcgSoftLimitInBytes(std::vector<std::string>&& args);
-    Result<Success> ParseMemcgSwappiness(std::vector<std::string>&& args);
-    Result<Success> ParseNamespace(std::vector<std::string>&& args);
-    Result<Success> ParseProcessRlimit(std::vector<std::string>&& args);
-    Result<Success> ParseRestartPeriod(std::vector<std::string>&& args);
-    Result<Success> ParseSeclabel(std::vector<std::string>&& args);
-    Result<Success> ParseSetenv(std::vector<std::string>&& args);
-    Result<Success> ParseShutdown(std::vector<std::string>&& args);
-    Result<Success> ParseSigstop(std::vector<std::string>&& args);
-    Result<Success> ParseSocket(std::vector<std::string>&& args);
-    Result<Success> ParseTimeoutPeriod(std::vector<std::string>&& args);
-    Result<Success> ParseFile(std::vector<std::string>&& args);
-    Result<Success> ParseUser(std::vector<std::string>&& args);
-    Result<Success> ParseWritepid(std::vector<std::string>&& args);
-    Result<Success> ParseUpdatable(std::vector<std::string>&& args);
-
-    template <typename T>
-    Result<Success> AddDescriptor(std::vector<std::string>&& args);
+    void KillProcessGroup(int signal, bool report_oneshot = false);
+    void SetProcessAttributesAndCaps();
 
     static unsigned long next_start_order_;
     static bool is_exec_service_running_;
 
     std::string name_;
     std::set<std::string> classnames_;
-    std::string console_;
 
     unsigned flags_;
     pid_t pid_;
@@ -192,17 +149,14 @@
     android::base::boot_clock::time_point time_crashed_;  // first crash within inspection window
     int crash_count_;                     // number of times crashed within window
 
-    uid_t uid_;
-    gid_t gid_;
-    std::vector<gid_t> supp_gids_;
     std::optional<CapSet> capabilities_;
-    unsigned namespace_flags_;
-    // Pair of namespace type, path to namespace.
-    std::vector<std::pair<int, std::string>> namespaces_to_enter_;
+    ProcessAttributes proc_attr_;
+    NamespaceInfo namespaces_;
 
     std::string seclabel_;
 
-    std::vector<std::unique_ptr<DescriptorInfo>> descriptors_;
+    std::vector<SocketDescriptor> sockets_;
+    std::vector<FileDescriptor> files_;
     std::vector<std::pair<std::string, std::string>> environment_vars_;
 
     Action onrestart_;  // Commands to execute on restart.
@@ -214,10 +168,6 @@
     // keycodes for triggering this service via /dev/input/input*
     std::vector<int> keycodes_;
 
-    IoSchedClass ioprio_class_;
-    int ioprio_pri_;
-    int priority_;
-
     int oom_score_adjust_;
 
     int swappiness_ = -1;
@@ -233,8 +183,6 @@
 
     unsigned long start_order_;
 
-    std::vector<std::pair<int, rlimit>> rlimits_;
-
     bool sigstop_ = false;
 
     std::chrono::seconds restart_period_ = 5s;
@@ -251,81 +199,11 @@
     bool post_data_ = false;
 
     bool running_at_post_data_reset_ = false;
-};
 
-class ServiceList {
-  public:
-    static ServiceList& GetInstance();
+    std::optional<std::string> on_failure_reboot_target_;
 
-    // Exposed for testing
-    ServiceList();
-
-    void AddService(std::unique_ptr<Service> service);
-    void RemoveService(const Service& svc);
-
-    template <typename T, typename F = decltype(&Service::name)>
-    Service* FindService(T value, F function = &Service::name) const {
-        auto svc = std::find_if(services_.begin(), services_.end(),
-                                [&function, &value](const std::unique_ptr<Service>& s) {
-                                    return std::invoke(function, s) == value;
-                                });
-        if (svc != services_.end()) {
-            return svc->get();
-        }
-        return nullptr;
-    }
-
-    Service* FindInterface(const std::string& interface_name) {
-        for (const auto& svc : services_) {
-            if (svc->interfaces().count(interface_name) > 0) {
-                return svc.get();
-            }
-        }
-
-        return nullptr;
-    }
-
-    void DumpState() const;
-
-    auto begin() const { return services_.begin(); }
-    auto end() const { return services_.end(); }
-    const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
-    const std::vector<Service*> services_in_shutdown_order() const;
-
-    void MarkPostData();
-    bool IsPostData();
-    void MarkServicesUpdate();
-    bool IsServicesUpdated() const { return services_update_finished_; }
-    void DelayService(const Service& service);
-
-  private:
-    std::vector<std::unique_ptr<Service>> services_;
-
-    bool post_data_ = false;
-    bool services_update_finished_ = false;
-    std::vector<std::string> delayed_service_names_;
-};
-
-class ServiceParser : public SectionParser {
-  public:
-    ServiceParser(ServiceList* service_list, std::vector<Subcontext>* subcontexts)
-        : service_list_(service_list), subcontexts_(subcontexts), service_(nullptr) {}
-    Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
-                                 int line) override;
-    Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
-    Result<Success> EndSection() override;
-    void EndFile() override { filename_ = ""; }
-
-  private:
-    bool IsValidName(const std::string& name) const;
-
-    ServiceList* service_list_;
-    std::vector<Subcontext>* subcontexts_;
-    std::unique_ptr<Service> service_;
-    std::string filename_;
+    bool from_apex_ = false;
 };
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/service_list.cpp b/init/service_list.cpp
new file mode 100644
index 0000000..c51a9cf
--- /dev/null
+++ b/init/service_list.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 "service_list.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace init {
+
+ServiceList::ServiceList() {}
+
+ServiceList& ServiceList::GetInstance() {
+    static ServiceList instance;
+    return instance;
+}
+
+size_t ServiceList::CheckAllCommands() {
+    size_t failures = 0;
+    for (const auto& service : services_) {
+        failures += service->CheckAllCommands();
+    }
+    return failures;
+}
+
+void ServiceList::AddService(std::unique_ptr<Service> service) {
+    services_.emplace_back(std::move(service));
+}
+
+// Shutdown services in the opposite order that they were started.
+const std::vector<Service*> ServiceList::services_in_shutdown_order() const {
+    std::vector<Service*> shutdown_services;
+    for (const auto& service : services_) {
+        if (service->start_order() > 0) shutdown_services.emplace_back(service.get());
+    }
+    std::sort(shutdown_services.begin(), shutdown_services.end(),
+              [](const auto& a, const auto& b) { return a->start_order() > b->start_order(); });
+    return shutdown_services;
+}
+
+void ServiceList::RemoveService(const Service& svc) {
+    auto svc_it = std::find_if(
+            services_.begin(), services_.end(),
+            [&svc](const std::unique_ptr<Service>& s) { return svc.name() == s->name(); });
+    if (svc_it == services_.end()) {
+        return;
+    }
+
+    services_.erase(svc_it);
+}
+
+void ServiceList::DumpState() const {
+    for (const auto& s : services_) {
+        s->DumpState();
+    }
+}
+
+void ServiceList::MarkPostData() {
+    post_data_ = true;
+}
+
+bool ServiceList::IsPostData() {
+    return post_data_;
+}
+
+void ServiceList::MarkServicesUpdate() {
+    services_update_finished_ = true;
+
+    // start the delayed services
+    for (const auto& name : delayed_service_names_) {
+        Service* service = FindService(name);
+        if (service == nullptr) {
+            LOG(ERROR) << "delayed service '" << name << "' could not be found.";
+            continue;
+        }
+        if (auto result = service->Start(); !result) {
+            LOG(ERROR) << result.error().message();
+        }
+    }
+    delayed_service_names_.clear();
+}
+
+void ServiceList::DelayService(const Service& service) {
+    if (services_update_finished_) {
+        LOG(ERROR) << "Cannot delay the start of service '" << service.name()
+                   << "' because all services are already updated. Ignoring.";
+        return;
+    }
+    delayed_service_names_.emplace_back(service.name());
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/service_list.h b/init/service_list.h
new file mode 100644
index 0000000..1838624
--- /dev/null
+++ b/init/service_list.h
@@ -0,0 +1,87 @@
+/*
+ * 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 <memory>
+#include <vector>
+
+#include "service.h"
+
+namespace android {
+namespace init {
+
+class ServiceList {
+  public:
+    static ServiceList& GetInstance();
+
+    // Exposed for testing
+    ServiceList();
+    size_t CheckAllCommands();
+
+    void AddService(std::unique_ptr<Service> service);
+    void RemoveService(const Service& svc);
+    template <class UnaryPredicate>
+    void RemoveServiceIf(UnaryPredicate predicate) {
+        services_.erase(std::remove_if(services_.begin(), services_.end(), predicate),
+                        services_.end());
+    }
+
+    template <typename T, typename F = decltype(&Service::name)>
+    Service* FindService(T value, F function = &Service::name) const {
+        auto svc = std::find_if(services_.begin(), services_.end(),
+                                [&function, &value](const std::unique_ptr<Service>& s) {
+                                    return std::invoke(function, s) == value;
+                                });
+        if (svc != services_.end()) {
+            return svc->get();
+        }
+        return nullptr;
+    }
+
+    Service* FindInterface(const std::string& interface_name) {
+        for (const auto& svc : services_) {
+            if (svc->interfaces().count(interface_name) > 0) {
+                return svc.get();
+            }
+        }
+
+        return nullptr;
+    }
+
+    void DumpState() const;
+
+    auto begin() const { return services_.begin(); }
+    auto end() const { return services_.end(); }
+    const std::vector<std::unique_ptr<Service>>& services() const { return services_; }
+    const std::vector<Service*> services_in_shutdown_order() const;
+
+    void MarkPostData();
+    bool IsPostData();
+    void MarkServicesUpdate();
+    bool IsServicesUpdated() const { return services_update_finished_; }
+    void DelayService(const Service& service);
+
+  private:
+    std::vector<std::unique_ptr<Service>> services_;
+
+    bool post_data_ = false;
+    bool services_update_finished_ = false;
+    std::vector<std::string> delayed_service_names_;
+};
+
+}  // namespace init
+}  // namespace android
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
new file mode 100644
index 0000000..1d431e3
--- /dev/null
+++ b/init/service_parser.cpp
@@ -0,0 +1,631 @@
+/*
+ * 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 "service_parser.h"
+
+#include <linux/input.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+#include <algorithm>
+#include <sstream>
+
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <hidl-util/FQName.h>
+#include <system/thread_defs.h>
+
+#include "lmkd_service.h"
+#include "rlimit_parser.h"
+#include "service_utils.h"
+#include "util.h"
+
+#if defined(__ANDROID__)
+#include <android/api-level.h>
+#include <sys/system_properties.h>
+
+#include "selinux.h"
+#else
+#include "host_init_stubs.h"
+#endif
+
+using android::base::ParseInt;
+using android::base::Split;
+using android::base::StartsWith;
+
+namespace android {
+namespace init {
+
+Result<void> ServiceParser::ParseCapabilities(std::vector<std::string>&& args) {
+    service_->capabilities_ = 0;
+
+    if (!CapAmbientSupported()) {
+        return Error()
+               << "capabilities requested but the kernel does not support ambient capabilities";
+    }
+
+    unsigned int last_valid_cap = GetLastValidCap();
+    if (last_valid_cap >= service_->capabilities_->size()) {
+        LOG(WARNING) << "last valid run-time capability is larger than CAP_LAST_CAP";
+    }
+
+    for (size_t i = 1; i < args.size(); i++) {
+        const std::string& arg = args[i];
+        int res = LookupCap(arg);
+        if (res < 0) {
+            return Errorf("invalid capability '{}'", arg);
+        }
+        unsigned int cap = static_cast<unsigned int>(res);  // |res| is >= 0.
+        if (cap > last_valid_cap) {
+            return Errorf("capability '{}' not supported by the kernel", arg);
+        }
+        (*service_->capabilities_)[cap] = true;
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseClass(std::vector<std::string>&& args) {
+    service_->classnames_ = std::set<std::string>(args.begin() + 1, args.end());
+    return {};
+}
+
+Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) {
+    if (service_->proc_attr_.stdio_to_kmsg) {
+        return Error() << "'console' and 'stdio_to_kmsg' are mutually exclusive";
+    }
+    service_->flags_ |= SVC_CONSOLE;
+    service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : "";
+    return {};
+}
+
+Result<void> ServiceParser::ParseCritical(std::vector<std::string>&& args) {
+    service_->flags_ |= SVC_CRITICAL;
+    return {};
+}
+
+Result<void> ServiceParser::ParseDisabled(std::vector<std::string>&& args) {
+    service_->flags_ |= SVC_DISABLED;
+    service_->flags_ |= SVC_RC_DISABLED;
+    return {};
+}
+
+Result<void> ServiceParser::ParseEnterNamespace(std::vector<std::string>&& args) {
+    if (args[1] != "net") {
+        return Error() << "Init only supports entering network namespaces";
+    }
+    if (!service_->namespaces_.namespaces_to_enter.empty()) {
+        return Error() << "Only one network namespace may be entered";
+    }
+    // Network namespaces require that /sys is remounted, otherwise the old adapters will still be
+    // present. Therefore, they also require mount namespaces.
+    service_->namespaces_.flags |= CLONE_NEWNS;
+    service_->namespaces_.namespaces_to_enter.emplace_back(CLONE_NEWNET, std::move(args[2]));
+    return {};
+}
+
+Result<void> ServiceParser::ParseGroup(std::vector<std::string>&& args) {
+    auto gid = DecodeUid(args[1]);
+    if (!gid) {
+        return Error() << "Unable to decode GID for '" << args[1] << "': " << gid.error();
+    }
+    service_->proc_attr_.gid = *gid;
+
+    for (std::size_t n = 2; n < args.size(); n++) {
+        gid = DecodeUid(args[n]);
+        if (!gid) {
+            return Error() << "Unable to decode GID for '" << args[n] << "': " << gid.error();
+        }
+        service_->proc_attr_.supp_gids.emplace_back(*gid);
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParsePriority(std::vector<std::string>&& args) {
+    service_->proc_attr_.priority = 0;
+    if (!ParseInt(args[1], &service_->proc_attr_.priority,
+                  static_cast<int>(ANDROID_PRIORITY_HIGHEST),  // highest is negative
+                  static_cast<int>(ANDROID_PRIORITY_LOWEST))) {
+        return Errorf("process priority value must be range {} - {}", ANDROID_PRIORITY_HIGHEST,
+                      ANDROID_PRIORITY_LOWEST);
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseInterface(std::vector<std::string>&& args) {
+    const std::string& interface_name = args[1];
+    const std::string& instance_name = args[2];
+
+    // AIDL services don't use fully qualified names and instead just use "interface aidl <name>"
+    if (interface_name != "aidl") {
+        FQName fq_name;
+        if (!FQName::parse(interface_name, &fq_name)) {
+            return Error() << "Invalid fully-qualified name for interface '" << interface_name
+                           << "'";
+        }
+
+        if (!fq_name.isFullyQualified()) {
+            return Error() << "Interface name not fully-qualified '" << interface_name << "'";
+        }
+
+        if (fq_name.isValidValueName()) {
+            return Error() << "Interface name must not be a value name '" << interface_name << "'";
+        }
+    }
+
+    const std::string fullname = interface_name + "/" + instance_name;
+
+    for (const auto& svc : *service_list_) {
+        if (svc->interfaces().count(fullname) > 0) {
+            return Error() << "Interface '" << fullname << "' redefined in " << service_->name()
+                           << " but is already defined by " << svc->name();
+        }
+    }
+
+    service_->interfaces_.insert(fullname);
+
+    return {};
+}
+
+Result<void> ServiceParser::ParseIoprio(std::vector<std::string>&& args) {
+    if (!ParseInt(args[2], &service_->proc_attr_.ioprio_pri, 0, 7)) {
+        return Error() << "priority value must be range 0 - 7";
+    }
+
+    if (args[1] == "rt") {
+        service_->proc_attr_.ioprio_class = IoSchedClass_RT;
+    } else if (args[1] == "be") {
+        service_->proc_attr_.ioprio_class = IoSchedClass_BE;
+    } else if (args[1] == "idle") {
+        service_->proc_attr_.ioprio_class = IoSchedClass_IDLE;
+    } else {
+        return Error() << "ioprio option usage: ioprio <rt|be|idle> <0-7>";
+    }
+
+    return {};
+}
+
+Result<void> ServiceParser::ParseKeycodes(std::vector<std::string>&& args) {
+    auto it = args.begin() + 1;
+    if (args.size() == 2 && StartsWith(args[1], "$")) {
+        auto expanded = ExpandProps(args[1]);
+        if (!expanded) {
+            return expanded.error();
+        }
+
+        // If the property is not set, it defaults to none, in which case there are no keycodes
+        // for this service.
+        if (expanded == "none") {
+            return {};
+        }
+
+        args = Split(*expanded, ",");
+        it = args.begin();
+    }
+
+    for (; it != args.end(); ++it) {
+        int code;
+        if (ParseInt(*it, &code, 0, KEY_MAX)) {
+            for (auto& key : service_->keycodes_) {
+                if (key == code) return Error() << "duplicate keycode: " << *it;
+            }
+            service_->keycodes_.insert(
+                    std::upper_bound(service_->keycodes_.begin(), service_->keycodes_.end(), code),
+                    code);
+        } else {
+            return Error() << "invalid keycode: " << *it;
+        }
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseOneshot(std::vector<std::string>&& args) {
+    service_->flags_ |= SVC_ONESHOT;
+    return {};
+}
+
+Result<void> ServiceParser::ParseOnrestart(std::vector<std::string>&& args) {
+    args.erase(args.begin());
+    int line = service_->onrestart_.NumCommands() + 1;
+    if (auto result = service_->onrestart_.AddCommand(std::move(args), line); !result) {
+        return Error() << "cannot add Onrestart command: " << result.error();
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseNamespace(std::vector<std::string>&& args) {
+    for (size_t i = 1; i < args.size(); i++) {
+        if (args[i] == "pid") {
+            service_->namespaces_.flags |= CLONE_NEWPID;
+            // PID namespaces require mount namespaces.
+            service_->namespaces_.flags |= CLONE_NEWNS;
+        } else if (args[i] == "mnt") {
+            service_->namespaces_.flags |= CLONE_NEWNS;
+        } else {
+            return Error() << "namespace must be 'pid' or 'mnt'";
+        }
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseOomScoreAdjust(std::vector<std::string>&& args) {
+    if (!ParseInt(args[1], &service_->oom_score_adjust_, MIN_OOM_SCORE_ADJUST,
+                  MAX_OOM_SCORE_ADJUST)) {
+        return Error() << "oom_score_adjust value must be in range " << MIN_OOM_SCORE_ADJUST
+                       << " - +" << MAX_OOM_SCORE_ADJUST;
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseOverride(std::vector<std::string>&& args) {
+    service_->override_ = true;
+    return {};
+}
+
+Result<void> ServiceParser::ParseMemcgSwappiness(std::vector<std::string>&& args) {
+    if (!ParseInt(args[1], &service_->swappiness_, 0)) {
+        return Error() << "swappiness value must be equal or greater than 0";
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseMemcgLimitInBytes(std::vector<std::string>&& args) {
+    if (!ParseInt(args[1], &service_->limit_in_bytes_, 0)) {
+        return Error() << "limit_in_bytes value must be equal or greater than 0";
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseMemcgLimitPercent(std::vector<std::string>&& args) {
+    if (!ParseInt(args[1], &service_->limit_percent_, 0)) {
+        return Error() << "limit_percent value must be equal or greater than 0";
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseMemcgLimitProperty(std::vector<std::string>&& args) {
+    service_->limit_property_ = std::move(args[1]);
+    return {};
+}
+
+Result<void> ServiceParser::ParseMemcgSoftLimitInBytes(std::vector<std::string>&& args) {
+    if (!ParseInt(args[1], &service_->soft_limit_in_bytes_, 0)) {
+        return Error() << "soft_limit_in_bytes value must be equal or greater than 0";
+    }
+    return {};
+}
+
+Result<void> ServiceParser::ParseProcessRlimit(std::vector<std::string>&& args) {
+    auto rlimit = ParseRlimit(args);
+    if (!rlimit) return rlimit.error();
+
+    service_->proc_attr_.rlimits.emplace_back(*rlimit);
+    return {};
+}
+
+Result<void> ServiceParser::ParseRebootOnFailure(std::vector<std::string>&& args) {
+    if (service_->on_failure_reboot_target_) {
+        return Error() << "Only one reboot_on_failure command may be specified";
+    }
+    if (!StartsWith(args[1], "shutdown") && !StartsWith(args[1], "reboot")) {
+        return Error()
+               << "reboot_on_failure commands must begin with either 'shutdown' or 'reboot'";
+    }
+    service_->on_failure_reboot_target_ = std::move(args[1]);
+    return {};
+}
+
+Result<void> ServiceParser::ParseRestartPeriod(std::vector<std::string>&& args) {
+    int period;
+    if (!ParseInt(args[1], &period, 5)) {
+        return Error() << "restart_period value must be an integer >= 5";
+    }
+    service_->restart_period_ = std::chrono::seconds(period);
+    return {};
+}
+
+Result<void> ServiceParser::ParseSeclabel(std::vector<std::string>&& args) {
+    service_->seclabel_ = std::move(args[1]);
+    return {};
+}
+
+Result<void> ServiceParser::ParseSigstop(std::vector<std::string>&& args) {
+    service_->sigstop_ = true;
+    return {};
+}
+
+Result<void> ServiceParser::ParseSetenv(std::vector<std::string>&& args) {
+    service_->environment_vars_.emplace_back(std::move(args[1]), std::move(args[2]));
+    return {};
+}
+
+Result<void> ServiceParser::ParseShutdown(std::vector<std::string>&& args) {
+    if (args[1] == "critical") {
+        service_->flags_ |= SVC_SHUTDOWN_CRITICAL;
+        return {};
+    }
+    return Error() << "Invalid shutdown option";
+}
+
+Result<void> ServiceParser::ParseTimeoutPeriod(std::vector<std::string>&& args) {
+    int period;
+    if (!ParseInt(args[1], &period, 1)) {
+        return Error() << "timeout_period value must be an integer >= 1";
+    }
+    service_->timeout_period_ = std::chrono::seconds(period);
+    return {};
+}
+
+// name type perm [ uid gid context ]
+Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) {
+    SocketDescriptor socket;
+    socket.name = std::move(args[1]);
+
+    auto types = Split(args[2], "+");
+    if (types[0] == "stream") {
+        socket.type = SOCK_STREAM;
+    } else if (types[0] == "dgram") {
+        socket.type = SOCK_DGRAM;
+    } else if (types[0] == "seqpacket") {
+        socket.type = SOCK_SEQPACKET;
+    } else {
+        return Error() << "socket type must be 'dgram', 'stream' or 'seqpacket', got '" << types[0]
+                       << "' instead.";
+    }
+
+    if (types.size() > 1) {
+        if (types.size() == 2 && types[1] == "passcred") {
+            socket.passcred = true;
+        } else {
+            return Error() << "Only 'passcred' may be used to modify the socket type";
+        }
+    }
+
+    errno = 0;
+    char* end = nullptr;
+    socket.perm = strtol(args[3].c_str(), &end, 8);
+    if (errno != 0) {
+        return ErrnoError() << "Unable to parse permissions '" << args[3] << "'";
+    }
+    if (end == args[3].c_str() || *end != '\0') {
+        errno = EINVAL;
+        return ErrnoError() << "Unable to parse permissions '" << args[3] << "'";
+    }
+
+    if (args.size() > 4) {
+        auto uid = DecodeUid(args[4]);
+        if (!uid) {
+            return Error() << "Unable to find UID for '" << args[4] << "': " << uid.error();
+        }
+        socket.uid = *uid;
+    }
+
+    if (args.size() > 5) {
+        auto gid = DecodeUid(args[5]);
+        if (!gid) {
+            return Error() << "Unable to find GID for '" << args[5] << "': " << gid.error();
+        }
+        socket.gid = *gid;
+    }
+
+    socket.context = args.size() > 6 ? args[6] : "";
+
+    auto old = std::find_if(service_->sockets_.begin(), service_->sockets_.end(),
+                            [&socket](const auto& other) { return socket.name == other.name; });
+
+    if (old != service_->sockets_.end()) {
+        return Error() << "duplicate socket descriptor '" << socket.name << "'";
+    }
+
+    service_->sockets_.emplace_back(std::move(socket));
+
+    return {};
+}
+
+Result<void> ServiceParser::ParseStdioToKmsg(std::vector<std::string>&& args) {
+    if (service_->flags_ & SVC_CONSOLE) {
+        return Error() << "'stdio_to_kmsg' and 'console' are mutually exclusive";
+    }
+    service_->proc_attr_.stdio_to_kmsg = true;
+    return {};
+}
+
+// name type
+Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) {
+    if (args[2] != "r" && args[2] != "w" && args[2] != "rw") {
+        return Error() << "file type must be 'r', 'w' or 'rw'";
+    }
+
+    FileDescriptor file;
+    file.type = args[2];
+
+    auto file_name = ExpandProps(args[1]);
+    if (!file_name) {
+        return Error() << "Could not expand file path ': " << file_name.error();
+    }
+    file.name = *file_name;
+    if (file.name[0] != '/' || file.name.find("../") != std::string::npos) {
+        return Error() << "file name must not be relative";
+    }
+
+    auto old = std::find_if(service_->files_.begin(), service_->files_.end(),
+                            [&file](const auto& other) { return other.name == file.name; });
+
+    if (old != service_->files_.end()) {
+        return Error() << "duplicate file descriptor '" << file.name << "'";
+    }
+
+    service_->files_.emplace_back(std::move(file));
+
+    return {};
+}
+
+Result<void> ServiceParser::ParseUser(std::vector<std::string>&& args) {
+    auto uid = DecodeUid(args[1]);
+    if (!uid) {
+        return Error() << "Unable to find UID for '" << args[1] << "': " << uid.error();
+    }
+    service_->proc_attr_.uid = *uid;
+    return {};
+}
+
+Result<void> ServiceParser::ParseWritepid(std::vector<std::string>&& args) {
+    args.erase(args.begin());
+    service_->writepid_files_ = std::move(args);
+    return {};
+}
+
+Result<void> ServiceParser::ParseUpdatable(std::vector<std::string>&& args) {
+    service_->updatable_ = true;
+    return {};
+}
+
+const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() const {
+    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
+    // clang-format off
+    static const KeywordMap<ServiceParser::OptionParser> parser_map = {
+        {"capabilities",            {0,     kMax, &ServiceParser::ParseCapabilities}},
+        {"class",                   {1,     kMax, &ServiceParser::ParseClass}},
+        {"console",                 {0,     1,    &ServiceParser::ParseConsole}},
+        {"critical",                {0,     0,    &ServiceParser::ParseCritical}},
+        {"disabled",                {0,     0,    &ServiceParser::ParseDisabled}},
+        {"enter_namespace",         {2,     2,    &ServiceParser::ParseEnterNamespace}},
+        {"file",                    {2,     2,    &ServiceParser::ParseFile}},
+        {"group",                   {1,     NR_SVC_SUPP_GIDS + 1, &ServiceParser::ParseGroup}},
+        {"interface",               {2,     2,    &ServiceParser::ParseInterface}},
+        {"ioprio",                  {2,     2,    &ServiceParser::ParseIoprio}},
+        {"keycodes",                {1,     kMax, &ServiceParser::ParseKeycodes}},
+        {"memcg.limit_in_bytes",    {1,     1,    &ServiceParser::ParseMemcgLimitInBytes}},
+        {"memcg.limit_percent",     {1,     1,    &ServiceParser::ParseMemcgLimitPercent}},
+        {"memcg.limit_property",    {1,     1,    &ServiceParser::ParseMemcgLimitProperty}},
+        {"memcg.soft_limit_in_bytes",
+                                    {1,     1,    &ServiceParser::ParseMemcgSoftLimitInBytes}},
+        {"memcg.swappiness",        {1,     1,    &ServiceParser::ParseMemcgSwappiness}},
+        {"namespace",               {1,     2,    &ServiceParser::ParseNamespace}},
+        {"oneshot",                 {0,     0,    &ServiceParser::ParseOneshot}},
+        {"onrestart",               {1,     kMax, &ServiceParser::ParseOnrestart}},
+        {"oom_score_adjust",        {1,     1,    &ServiceParser::ParseOomScoreAdjust}},
+        {"override",                {0,     0,    &ServiceParser::ParseOverride}},
+        {"priority",                {1,     1,    &ServiceParser::ParsePriority}},
+        {"reboot_on_failure",       {1,     1,    &ServiceParser::ParseRebootOnFailure}},
+        {"restart_period",          {1,     1,    &ServiceParser::ParseRestartPeriod}},
+        {"rlimit",                  {3,     3,    &ServiceParser::ParseProcessRlimit}},
+        {"seclabel",                {1,     1,    &ServiceParser::ParseSeclabel}},
+        {"setenv",                  {2,     2,    &ServiceParser::ParseSetenv}},
+        {"shutdown",                {1,     1,    &ServiceParser::ParseShutdown}},
+        {"sigstop",                 {0,     0,    &ServiceParser::ParseSigstop}},
+        {"socket",                  {3,     6,    &ServiceParser::ParseSocket}},
+        {"stdio_to_kmsg",           {0,     0,    &ServiceParser::ParseStdioToKmsg}},
+        {"timeout_period",          {1,     1,    &ServiceParser::ParseTimeoutPeriod}},
+        {"updatable",               {0,     0,    &ServiceParser::ParseUpdatable}},
+        {"user",                    {1,     1,    &ServiceParser::ParseUser}},
+        {"writepid",                {1,     kMax, &ServiceParser::ParseWritepid}},
+    };
+    // clang-format on
+    return parser_map;
+}
+
+Result<void> ServiceParser::ParseSection(std::vector<std::string>&& args,
+                                         const std::string& filename, int line) {
+    if (args.size() < 3) {
+        return Error() << "services must have a name and a program";
+    }
+
+    const std::string& name = args[1];
+    if (!IsValidName(name)) {
+        return Error() << "invalid service name '" << name << "'";
+    }
+
+    filename_ = filename;
+
+    Subcontext* restart_action_subcontext = nullptr;
+    if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
+        restart_action_subcontext = subcontext_;
+    }
+
+    std::vector<std::string> str_args(args.begin() + 2, args.end());
+
+    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
+        if (str_args[0] == "/sbin/watchdogd") {
+            str_args[0] = "/system/bin/watchdogd";
+        }
+    }
+    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
+        if (str_args[0] == "/charger") {
+            str_args[0] = "/system/bin/charger";
+        }
+    }
+
+    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args, from_apex_);
+    return {};
+}
+
+Result<void> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
+    if (!service_) {
+        return {};
+    }
+
+    auto parser = GetParserMap().Find(args);
+
+    if (!parser) return parser.error();
+
+    return std::invoke(*parser, this, std::move(args));
+}
+
+Result<void> ServiceParser::EndSection() {
+    if (!service_) {
+        return {};
+    }
+
+    if (interface_inheritance_hierarchy_) {
+        if (const auto& check_hierarchy_result = CheckInterfaceInheritanceHierarchy(
+                    service_->interfaces(), *interface_inheritance_hierarchy_);
+            !check_hierarchy_result) {
+            return Error() << check_hierarchy_result.error();
+        }
+    }
+
+    Service* old_service = service_list_->FindService(service_->name());
+    if (old_service) {
+        if (!service_->is_override()) {
+            return Error() << "ignored duplicate definition of service '" << service_->name()
+                           << "'";
+        }
+
+        if (StartsWith(filename_, "/apex/") && !old_service->is_updatable()) {
+            return Error() << "cannot update a non-updatable service '" << service_->name()
+                           << "' with a config in APEX";
+        }
+
+        service_list_->RemoveService(*old_service);
+        old_service = nullptr;
+    }
+
+    service_list_->AddService(std::move(service_));
+
+    return {};
+}
+
+bool ServiceParser::IsValidName(const std::string& name) const {
+    // Property names can be any length, but may only contain certain characters.
+    // Property values can contain any characters, but may only be a certain length.
+    // (The latter restriction is needed because `start` and `stop` work by writing
+    // the service name to the "ctl.start" and "ctl.stop" properties.)
+    return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/service_parser.h b/init/service_parser.h
new file mode 100644
index 0000000..7bb0cc0
--- /dev/null
+++ b/init/service_parser.h
@@ -0,0 +1,98 @@
+/*
+ * 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 <vector>
+
+#include "interface_utils.h"
+#include "parser.h"
+#include "service.h"
+#include "service_list.h"
+#include "subcontext.h"
+
+namespace android {
+namespace init {
+
+class ServiceParser : public SectionParser {
+  public:
+    ServiceParser(
+            ServiceList* service_list, Subcontext* subcontext,
+            const std::optional<InterfaceInheritanceHierarchyMap>& interface_inheritance_hierarchy,
+            bool from_apex = false)
+        : service_list_(service_list),
+          subcontext_(subcontext),
+          interface_inheritance_hierarchy_(interface_inheritance_hierarchy),
+          service_(nullptr),
+          from_apex_(from_apex) {}
+    Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
+                              int line) override;
+    Result<void> ParseLineSection(std::vector<std::string>&& args, int line) override;
+    Result<void> EndSection() override;
+    void EndFile() override { filename_ = ""; }
+
+  private:
+    using OptionParser = Result<void> (ServiceParser::*)(std::vector<std::string>&& args);
+    const KeywordMap<ServiceParser::OptionParser>& GetParserMap() const;
+
+    Result<void> ParseCapabilities(std::vector<std::string>&& args);
+    Result<void> ParseClass(std::vector<std::string>&& args);
+    Result<void> ParseConsole(std::vector<std::string>&& args);
+    Result<void> ParseCritical(std::vector<std::string>&& args);
+    Result<void> ParseDisabled(std::vector<std::string>&& args);
+    Result<void> ParseEnterNamespace(std::vector<std::string>&& args);
+    Result<void> ParseGroup(std::vector<std::string>&& args);
+    Result<void> ParsePriority(std::vector<std::string>&& args);
+    Result<void> ParseInterface(std::vector<std::string>&& args);
+    Result<void> ParseIoprio(std::vector<std::string>&& args);
+    Result<void> ParseKeycodes(std::vector<std::string>&& args);
+    Result<void> ParseOneshot(std::vector<std::string>&& args);
+    Result<void> ParseOnrestart(std::vector<std::string>&& args);
+    Result<void> ParseOomScoreAdjust(std::vector<std::string>&& args);
+    Result<void> ParseOverride(std::vector<std::string>&& args);
+    Result<void> ParseMemcgLimitInBytes(std::vector<std::string>&& args);
+    Result<void> ParseMemcgLimitPercent(std::vector<std::string>&& args);
+    Result<void> ParseMemcgLimitProperty(std::vector<std::string>&& args);
+    Result<void> ParseMemcgSoftLimitInBytes(std::vector<std::string>&& args);
+    Result<void> ParseMemcgSwappiness(std::vector<std::string>&& args);
+    Result<void> ParseNamespace(std::vector<std::string>&& args);
+    Result<void> ParseProcessRlimit(std::vector<std::string>&& args);
+    Result<void> ParseRebootOnFailure(std::vector<std::string>&& args);
+    Result<void> ParseRestartPeriod(std::vector<std::string>&& args);
+    Result<void> ParseSeclabel(std::vector<std::string>&& args);
+    Result<void> ParseSetenv(std::vector<std::string>&& args);
+    Result<void> ParseShutdown(std::vector<std::string>&& args);
+    Result<void> ParseSigstop(std::vector<std::string>&& args);
+    Result<void> ParseSocket(std::vector<std::string>&& args);
+    Result<void> ParseStdioToKmsg(std::vector<std::string>&& args);
+    Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args);
+    Result<void> ParseFile(std::vector<std::string>&& args);
+    Result<void> ParseUser(std::vector<std::string>&& args);
+    Result<void> ParseWritepid(std::vector<std::string>&& args);
+    Result<void> ParseUpdatable(std::vector<std::string>&& args);
+
+    bool IsValidName(const std::string& name) const;
+
+    ServiceList* service_list_;
+    Subcontext* subcontext_;
+    std::optional<InterfaceInheritanceHierarchyMap> interface_inheritance_hierarchy_;
+    std::unique_ptr<Service> service_;
+    std::string filename_;
+    bool from_apex_ = false;
+};
+
+}  // namespace init
+}  // namespace android
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 4bfaa6b..c158b0a 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -23,6 +23,7 @@
 
 #include <gtest/gtest.h>
 
+#include "lmkd_service.h"
 #include "util.h"
 
 namespace android {
@@ -30,7 +31,7 @@
 
 TEST(service, pod_initialized) {
     constexpr auto memory_size = sizeof(Service);
-    alignas(alignof(Service)) char old_memory[memory_size];
+    alignas(alignof(Service)) unsigned char old_memory[memory_size];
 
     for (std::size_t i = 0; i < memory_size; ++i) {
         old_memory[i] = 0xFF;
@@ -45,11 +46,11 @@
     EXPECT_EQ(0, service_in_old_memory->crash_count());
     EXPECT_EQ(0U, service_in_old_memory->uid());
     EXPECT_EQ(0U, service_in_old_memory->gid());
-    EXPECT_EQ(0U, service_in_old_memory->namespace_flags());
+    EXPECT_EQ(0, service_in_old_memory->namespace_flags());
     EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory->ioprio_class());
     EXPECT_EQ(0, service_in_old_memory->ioprio_pri());
     EXPECT_EQ(0, service_in_old_memory->priority());
-    EXPECT_EQ(-1000, service_in_old_memory->oom_score_adjust());
+    EXPECT_EQ(DEFAULT_OOM_SCORE_ADJUST, service_in_old_memory->oom_score_adjust());
     EXPECT_FALSE(service_in_old_memory->process_cgroup_empty());
 
     for (std::size_t i = 0; i < memory_size; ++i) {
@@ -64,26 +65,26 @@
     EXPECT_EQ(0, service_in_old_memory2->crash_count());
     EXPECT_EQ(0U, service_in_old_memory2->uid());
     EXPECT_EQ(0U, service_in_old_memory2->gid());
-    EXPECT_EQ(0U, service_in_old_memory2->namespace_flags());
+    EXPECT_EQ(0, service_in_old_memory2->namespace_flags());
     EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory2->ioprio_class());
     EXPECT_EQ(0, service_in_old_memory2->ioprio_pri());
     EXPECT_EQ(0, service_in_old_memory2->priority());
-    EXPECT_EQ(-1000, service_in_old_memory2->oom_score_adjust());
+    EXPECT_EQ(DEFAULT_OOM_SCORE_ADJUST, service_in_old_memory2->oom_score_adjust());
     EXPECT_FALSE(service_in_old_memory->process_cgroup_empty());
 }
 
 TEST(service, make_temporary_oneshot_service_invalid_syntax) {
     std::vector<std::string> args;
     // Nothing.
-    ASSERT_EQ(nullptr, Service::MakeTemporaryOneshotService(args));
+    ASSERT_FALSE(Service::MakeTemporaryOneshotService(args));
 
     // No arguments to 'exec'.
     args.push_back("exec");
-    ASSERT_EQ(nullptr, Service::MakeTemporaryOneshotService(args));
+    ASSERT_FALSE(Service::MakeTemporaryOneshotService(args));
 
     // No command in "exec --".
     args.push_back("--");
-    ASSERT_EQ(nullptr, Service::MakeTemporaryOneshotService(args));
+    ASSERT_FALSE(Service::MakeTemporaryOneshotService(args));
 }
 
 TEST(service, make_temporary_oneshot_service_too_many_supplementary_gids) {
@@ -97,7 +98,7 @@
     }
     args.push_back("--");
     args.push_back("/system/bin/id");
-    ASSERT_EQ(nullptr, Service::MakeTemporaryOneshotService(args));
+    ASSERT_FALSE(Service::MakeTemporaryOneshotService(args));
 }
 
 static void Test_make_temporary_oneshot_service(bool dash_dash, bool seclabel, bool uid, bool gid,
@@ -122,8 +123,9 @@
     }
     args.push_back("/system/bin/toybox");
     args.push_back("id");
-    auto svc = Service::MakeTemporaryOneshotService(args);
-    ASSERT_NE(nullptr, svc);
+    auto service_ret = Service::MakeTemporaryOneshotService(args);
+    ASSERT_TRUE(service_ret);
+    auto svc = std::move(*service_ret);
 
     if (seclabel) {
         ASSERT_EQ("u:r:su:s0", svc->seclabel());
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
new file mode 100644
index 0000000..93cffd8
--- /dev/null
+++ b/init/service_utils.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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 "service_utils.h"
+
+#include <fcntl.h>
+#include <grp.h>
+#include <sys/mount.h>
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#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 <cutils/android_get_control_file.h>
+#include <cutils/sockets.h>
+#include <processgroup/processgroup.h>
+
+#include "mount_namespace.h"
+#include "util.h"
+
+using android::base::GetProperty;
+using android::base::StartsWith;
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::base::WriteStringToFile;
+
+namespace android {
+namespace init {
+
+namespace {
+
+Result<void> EnterNamespace(int nstype, const char* path) {
+    auto fd = unique_fd{open(path, O_RDONLY | O_CLOEXEC)};
+    if (fd == -1) {
+        return ErrnoError() << "Could not open namespace at " << path;
+    }
+    if (setns(fd, nstype) == -1) {
+        return ErrnoError() << "Could not setns() namespace at " << path;
+    }
+    return {};
+}
+
+Result<void> SetUpMountNamespace(bool remount_proc, bool remount_sys) {
+    constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID;
+
+    // Recursively remount / as slave like zygote does so unmounting and mounting /proc
+    // doesn't interfere with the parent namespace's /proc mount. This will also
+    // prevent any other mounts/unmounts initiated by the service from interfering
+    // with the parent namespace but will still allow mount events from the parent
+    // namespace to propagate to the child.
+    if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
+        return ErrnoError() << "Could not remount(/) recursively as slave";
+    }
+
+    // umount() then mount() /proc and/or /sys
+    // Note that it is not sufficient to mount with MS_REMOUNT.
+    if (remount_proc) {
+        if (umount("/proc") == -1) {
+            return ErrnoError() << "Could not umount(/proc)";
+        }
+        if (mount("", "/proc", "proc", kSafeFlags, "") == -1) {
+            return ErrnoError() << "Could not mount(/proc)";
+        }
+    }
+    if (remount_sys) {
+        if (umount2("/sys", MNT_DETACH) == -1) {
+            return ErrnoError() << "Could not umount(/sys)";
+        }
+        if (mount("", "/sys", "sysfs", kSafeFlags, "") == -1) {
+            return ErrnoError() << "Could not mount(/sys)";
+        }
+    }
+    return {};
+}
+
+Result<void> SetUpPidNamespace(const char* name) {
+    if (prctl(PR_SET_NAME, name) == -1) {
+        return ErrnoError() << "Could not set name";
+    }
+
+    pid_t child_pid = fork();
+    if (child_pid == -1) {
+        return ErrnoError() << "Could not fork init inside the PID namespace";
+    }
+
+    if (child_pid > 0) {
+        // So that we exit with the right status.
+        static int init_exitstatus = 0;
+        signal(SIGTERM, [](int) { _exit(init_exitstatus); });
+
+        pid_t waited_pid;
+        int status;
+        while ((waited_pid = wait(&status)) > 0) {
+            // This loop will end when there are no processes left inside the
+            // PID namespace or when the init process inside the PID namespace
+            // gets a signal.
+            if (waited_pid == child_pid) {
+                init_exitstatus = status;
+            }
+        }
+        if (!WIFEXITED(init_exitstatus)) {
+            _exit(EXIT_FAILURE);
+        }
+        _exit(WEXITSTATUS(init_exitstatus));
+    }
+    return {};
+}
+
+void SetupStdio(bool stdio_to_kmsg) {
+    auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)};
+    dup2(fd, STDIN_FILENO);
+    if (stdio_to_kmsg) {
+        fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC));
+        if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC));
+    }
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
+}
+
+void OpenConsole(const std::string& console) {
+    auto fd = unique_fd{open(console.c_str(), O_RDWR | O_CLOEXEC)};
+    if (fd == -1) fd.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
+    ioctl(fd, TIOCSCTTY, 0);
+    dup2(fd, 0);
+    dup2(fd, 1);
+    dup2(fd, 2);
+}
+
+}  // namespace
+
+void Descriptor::Publish() const {
+    auto published_name = name_;
+
+    for (auto& c : published_name) {
+        c = isalnum(c) ? c : '_';
+    }
+
+    int fd = fd_.get();
+    // For safety, the FD is created as CLOEXEC, so that must be removed before publishing.
+    auto fd_flags = fcntl(fd, F_GETFD);
+    fd_flags &= ~FD_CLOEXEC;
+    if (fcntl(fd, F_SETFD, fd_flags) != 0) {
+        PLOG(ERROR) << "Failed to remove CLOEXEC from '" << published_name << "'";
+    }
+
+    std::string val = std::to_string(fd);
+    setenv(published_name.c_str(), val.c_str(), 1);
+}
+
+Result<Descriptor> SocketDescriptor::Create(const std::string& global_context) const {
+    const auto& socket_context = context.empty() ? global_context : context;
+    auto result = CreateSocket(name, type | SOCK_CLOEXEC, passcred, perm, uid, gid, socket_context);
+    if (!result) {
+        return result.error();
+    }
+
+    return Descriptor(ANDROID_SOCKET_ENV_PREFIX + name, unique_fd(*result));
+}
+
+Result<Descriptor> FileDescriptor::Create() const {
+    int flags = (type == "r") ? O_RDONLY : (type == "w") ? O_WRONLY : O_RDWR;
+
+    // Make sure we do not block on open (eg: devices can chose to block on carrier detect).  Our
+    // intention is never to delay launch of a service for such a condition.  The service can
+    // perform its own blocking on carrier detect.
+    unique_fd fd(TEMP_FAILURE_RETRY(open(name.c_str(), flags | O_NONBLOCK | O_CLOEXEC)));
+
+    if (fd < 0) {
+        return ErrnoError() << "Failed to open file '" << name << "'";
+    }
+
+    // Fixup as we set O_NONBLOCK for open, the intent for fd is to block reads.
+    fcntl(fd, F_SETFL, flags);
+
+    LOG(INFO) << "Opened file '" << name << "', flags " << flags;
+
+    return Descriptor(ANDROID_FILE_ENV_PREFIX + name, std::move(fd));
+}
+
+Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name, bool pre_apexd) {
+    for (const auto& [nstype, path] : info.namespaces_to_enter) {
+        if (auto result = EnterNamespace(nstype, path.c_str()); !result) {
+            return result;
+        }
+    }
+
+#if defined(__ANDROID__)
+    if (pre_apexd) {
+        if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
+            return Error() << "could not enter into the bootstrap mount namespace";
+        }
+    }
+#endif
+
+    if (info.flags & CLONE_NEWNS) {
+        bool remount_proc = info.flags & CLONE_NEWPID;
+        bool remount_sys =
+                std::any_of(info.namespaces_to_enter.begin(), info.namespaces_to_enter.end(),
+                            [](const auto& entry) { return entry.first == CLONE_NEWNET; });
+        if (auto result = SetUpMountNamespace(remount_proc, remount_sys); !result) {
+            return result;
+        }
+    }
+
+    if (info.flags & CLONE_NEWPID) {
+        // This will fork again to run an init process inside the PID namespace.
+        if (auto result = SetUpPidNamespace(name.c_str()); !result) {
+            return result;
+        }
+    }
+
+    return {};
+}
+
+Result<void> SetProcessAttributes(const ProcessAttributes& attr) {
+    if (attr.ioprio_class != IoSchedClass_NONE) {
+        if (android_set_ioprio(getpid(), attr.ioprio_class, attr.ioprio_pri)) {
+            PLOG(ERROR) << "failed to set pid " << getpid() << " ioprio=" << attr.ioprio_class
+                        << "," << attr.ioprio_pri;
+        }
+    }
+
+    if (!attr.console.empty()) {
+        setsid();
+        OpenConsole(attr.console);
+    } else {
+        if (setpgid(0, getpid()) == -1) {
+            return ErrnoError() << "setpgid failed";
+        }
+        SetupStdio(attr.stdio_to_kmsg);
+    }
+
+    for (const auto& rlimit : attr.rlimits) {
+        if (setrlimit(rlimit.first, &rlimit.second) == -1) {
+            return ErrnoError() << StringPrintf(
+                           "setrlimit(%d, {rlim_cur=%ld, rlim_max=%ld}) failed", rlimit.first,
+                           rlimit.second.rlim_cur, rlimit.second.rlim_max);
+        }
+    }
+
+    if (attr.gid) {
+        if (setgid(attr.gid) != 0) {
+            return ErrnoError() << "setgid failed";
+        }
+    }
+    if (setgroups(attr.supp_gids.size(), const_cast<gid_t*>(&attr.supp_gids[0])) != 0) {
+        return ErrnoError() << "setgroups failed";
+    }
+    if (attr.uid) {
+        if (setuid(attr.uid) != 0) {
+            return ErrnoError() << "setuid failed";
+        }
+    }
+
+    if (attr.priority != 0) {
+        if (setpriority(PRIO_PROCESS, 0, attr.priority) != 0) {
+            return ErrnoError() << "setpriority failed";
+        }
+    }
+    return {};
+}
+
+Result<void> WritePidToFiles(std::vector<std::string>* files) {
+    // See if there were "writepid" instructions to write to files under cpuset path.
+    std::string cpuset_path;
+    if (CgroupGetControllerPath("cpuset", &cpuset_path)) {
+        auto cpuset_predicate = [&cpuset_path](const std::string& path) {
+            return StartsWith(path, cpuset_path + "/");
+        };
+        auto iter = std::find_if(files->begin(), files->end(), cpuset_predicate);
+        if (iter == files->end()) {
+            // There were no "writepid" instructions for cpusets, check if the system default
+            // cpuset is specified to be used for the process.
+            std::string default_cpuset = GetProperty("ro.cpuset.default", "");
+            if (!default_cpuset.empty()) {
+                // Make sure the cpuset name starts and ends with '/'.
+                // A single '/' means the 'root' cpuset.
+                if (default_cpuset.front() != '/') {
+                    default_cpuset.insert(0, 1, '/');
+                }
+                if (default_cpuset.back() != '/') {
+                    default_cpuset.push_back('/');
+                }
+                files->push_back(
+                        StringPrintf("%s%stasks", cpuset_path.c_str(), default_cpuset.c_str()));
+            }
+        }
+    } else {
+        LOG(ERROR) << "cpuset cgroup controller is not mounted!";
+    }
+    std::string pid_str = std::to_string(getpid());
+    for (const auto& file : *files) {
+        if (!WriteStringToFile(pid_str, file)) {
+            return ErrnoError() << "couldn't write " << pid_str << " to " << file;
+        }
+    }
+    return {};
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/service_utils.h b/init/service_utils.h
new file mode 100644
index 0000000..3f1071e
--- /dev/null
+++ b/init/service_utils.h
@@ -0,0 +1,87 @@
+/*
+ * 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/resource.h>
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+#include <cutils/iosched_policy.h>
+
+#include "result.h"
+
+namespace android {
+namespace init {
+
+class Descriptor {
+  public:
+    Descriptor(const std::string& name, android::base::unique_fd fd)
+        : name_(name), fd_(std::move(fd)){};
+
+    void Publish() const;
+
+  private:
+    std::string name_;
+    android::base::unique_fd fd_;
+};
+
+struct SocketDescriptor {
+    std::string name;
+    int type = 0;
+    uid_t uid = 0;
+    gid_t gid = 0;
+    int perm = 0;
+    std::string context;
+    bool passcred = false;
+
+    Result<Descriptor> Create(const std::string& global_context) const;
+};
+
+struct FileDescriptor {
+    std::string name;
+    std::string type;
+
+    Result<Descriptor> Create() const;
+};
+
+struct NamespaceInfo {
+    int flags;
+    // Pair of namespace type, path to name.
+    std::vector<std::pair<int, std::string>> namespaces_to_enter;
+};
+Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name, bool pre_apexd);
+
+struct ProcessAttributes {
+    std::string console;
+    IoSchedClass ioprio_class;
+    int ioprio_pri;
+    std::vector<std::pair<int, rlimit>> rlimits;
+    uid_t uid;
+    gid_t gid;
+    std::vector<gid_t> supp_gids;
+    int priority;
+    bool stdio_to_kmsg;
+};
+Result<void> SetProcessAttributes(const ProcessAttributes& attr);
+
+Result<void> WritePidToFiles(std::vector<std::string>* files);
+
+}  // namespace init
+}  // namespace android
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 0b03324..9b2c7d9 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -28,28 +28,31 @@
 #include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 
-#include "init.h"
-#include "property_service.h"
-#include "service.h"
+#include <thread>
 
-using android::base::StringPrintf;
+#include "init.h"
+#include "service.h"
+#include "service_list.h"
+
 using android::base::boot_clock;
 using android::base::make_scope_guard;
+using android::base::StringPrintf;
+using android::base::Timer;
 
 namespace android {
 namespace init {
 
-static bool ReapOneProcess() {
+static pid_t ReapOneProcess() {
     siginfo_t siginfo = {};
     // This returns a zombie pid or informs us that there are no zombies left to be reaped.
     // It does NOT reap the pid; that is done below.
     if (TEMP_FAILURE_RETRY(waitid(P_ALL, 0, &siginfo, WEXITED | WNOHANG | WNOWAIT)) != 0) {
         PLOG(ERROR) << "waitid failed";
-        return false;
+        return 0;
     }
 
     auto pid = siginfo.si_pid;
-    if (pid == 0) return false;
+    if (pid == 0) return 0;
 
     // At this point we know we have a zombie pid, so we use this scopeguard to reap the pid
     // whenever the function returns from this point forward.
@@ -61,9 +64,7 @@
     std::string wait_string;
     Service* service = nullptr;
 
-    if (PropertyChildReap(pid)) {
-        name = "Async property child";
-    } else if (SubcontextChildReap(pid)) {
+    if (SubcontextChildReap(pid)) {
         name = "Subcontext";
     } else {
         service = ServiceList::GetInstance().FindService(pid, &Service::pid);
@@ -75,6 +76,13 @@
                 auto exec_duration_ms =
                     std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
                 wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
+            } else if (service->flags() & SVC_ONESHOT) {
+                auto exec_duration = boot_clock::now() - service->time_started();
+                auto exec_duration_ms =
+                        std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration)
+                                .count();
+                wait_string = StringPrintf(" oneshot service took %f seconds in background",
+                                           exec_duration_ms / 1000.0f);
             }
         } else {
             name = StringPrintf("Untracked pid %d", pid);
@@ -87,7 +95,7 @@
         LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string;
     }
 
-    if (!service) return true;
+    if (!service) return pid;
 
     service->Reap(siginfo);
 
@@ -95,13 +103,33 @@
         ServiceList::GetInstance().RemoveService(*service);
     }
 
-    return true;
+    return pid;
 }
 
 void ReapAnyOutstandingChildren() {
-    while (ReapOneProcess()) {
+    while (ReapOneProcess() != 0) {
     }
 }
 
+void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout) {
+    Timer t;
+    std::vector<pid_t> alive_pids(pids.begin(), pids.end());
+    while (!alive_pids.empty() && t.duration() < timeout) {
+        pid_t pid;
+        while ((pid = ReapOneProcess()) != 0) {
+            auto it = std::find(alive_pids.begin(), alive_pids.end(), pid);
+            if (it != alive_pids.end()) {
+                alive_pids.erase(it);
+            }
+        }
+        if (alive_pids.empty()) {
+            break;
+        }
+        std::this_thread::sleep_for(50ms);
+    }
+    LOG(INFO) << "Waiting for " << pids.size() << " pids to be reaped took " << t << " with "
+              << alive_pids.size() << " of them still running";
+}
+
 }  // namespace init
 }  // namespace android
diff --git a/init/sigchld_handler.h b/init/sigchld_handler.h
index 30063f2..fac1020 100644
--- a/init/sigchld_handler.h
+++ b/init/sigchld_handler.h
@@ -17,11 +17,16 @@
 #ifndef _INIT_SIGCHLD_HANDLER_H_
 #define _INIT_SIGCHLD_HANDLER_H_
 
+#include <chrono>
+#include <vector>
+
 namespace android {
 namespace init {
 
 void ReapAnyOutstandingChildren();
 
+void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout);
+
 }  // namespace init
 }  // namespace android
 
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 092c51c..f3f759d 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -18,20 +18,23 @@
 
 #include <fcntl.h>
 #include <poll.h>
-#include <sys/socket.h>
 #include <unistd.h>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <selinux/android.h>
 
 #include "action.h"
+#include "builtins.h"
+#include "proto_utils.h"
 #include "util.h"
 
 #if defined(__ANDROID__)
 #include <android/api-level.h>
 #include "property_service.h"
+#include "selabel.h"
 #include "selinux.h"
 #else
 #include "host_init_stubs.h"
@@ -46,59 +49,13 @@
 
 namespace android {
 namespace init {
-
-const std::string kInitContext = "u:r:init:s0";
-const std::string kVendorContext = "u:r:vendor_init:s0";
-
-const char* const paths_and_secontexts[2][2] = {
-    {"/vendor", kVendorContext.c_str()},
-    {"/odm", kVendorContext.c_str()},
-};
-
 namespace {
 
-constexpr size_t kBufferSize = 4096;
-
-Result<std::string> ReadMessage(int socket) {
-    char buffer[kBufferSize] = {};
-    auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0));
-    if (result == 0) {
-        return Error();
-    } else if (result < 0) {
-        return ErrnoError();
-    }
-    return std::string(buffer, result);
-}
-
-template <typename T>
-Result<Success> SendMessage(int socket, const T& message) {
-    std::string message_string;
-    if (!message.SerializeToString(&message_string)) {
-        return Error() << "Unable to serialize message";
-    }
-
-    if (message_string.size() > kBufferSize) {
-        return Error() << "Serialized message too long to send";
-    }
-
-    if (auto result =
-            TEMP_FAILURE_RETRY(send(socket, message_string.c_str(), message_string.size(), 0));
-        result != static_cast<long>(message_string.size())) {
-        return ErrnoError() << "send() failed to send message contents";
-    }
-    return Success();
-}
-
-std::vector<std::pair<std::string, std::string>> properties_to_set;
-
-uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) {
-    properties_to_set.emplace_back(name, value);
-    return 0;
-}
+std::string shutdown_command;
 
 class SubcontextProcess {
   public:
-    SubcontextProcess(const KeywordFunctionMap* function_map, std::string context, int init_fd)
+    SubcontextProcess(const BuiltinFunctionMap* function_map, std::string context, int init_fd)
         : function_map_(function_map), context_(std::move(context)), init_fd_(init_fd){};
     void MainLoop();
 
@@ -108,7 +65,7 @@
     void ExpandArgs(const SubcontextCommand::ExpandArgsCommand& expand_args_command,
                     SubcontextReply* reply) const;
 
-    const KeywordFunctionMap* function_map_;
+    const BuiltinFunctionMap* function_map_;
     const std::string context_;
     const int init_fd_;
 };
@@ -121,43 +78,35 @@
         args.emplace_back(string);
     }
 
-    auto map_result = function_map_->FindFunction(args);
-    Result<Success> result;
+    auto map_result = function_map_->Find(args);
+    Result<void> result;
     if (!map_result) {
         result = Error() << "Cannot find command: " << map_result.error();
     } else {
-        result = RunBuiltinFunction(map_result->second, args, context_);
+        result = RunBuiltinFunction(map_result->function, args, context_);
     }
 
-    for (const auto& [name, value] : properties_to_set) {
-        auto property = reply->add_properties_to_set();
-        property->set_name(name);
-        property->set_value(value);
-    }
-
-    properties_to_set.clear();
-
     if (result) {
         reply->set_success(true);
     } else {
         auto* failure = reply->mutable_failure();
-        failure->set_error_string(result.error_string());
-        failure->set_error_errno(result.error_errno());
+        failure->set_error_string(result.error().message());
+        failure->set_error_errno(result.error().code());
     }
 }
 
 void SubcontextProcess::ExpandArgs(const SubcontextCommand::ExpandArgsCommand& expand_args_command,
                                    SubcontextReply* reply) const {
     for (const auto& arg : expand_args_command.args()) {
-        auto expanded_prop = std::string{};
-        if (!expand_props(arg, &expanded_prop)) {
+        auto expanded_arg = ExpandProps(arg);
+        if (!expanded_arg) {
             auto* failure = reply->mutable_failure();
-            failure->set_error_string("Failed to expand '" + arg + "'");
+            failure->set_error_string(expanded_arg.error().message());
             failure->set_error_errno(0);
             return;
         } else {
             auto* expand_args_reply = reply->mutable_expand_args_reply();
-            expand_args_reply->add_expanded_args(expanded_prop);
+            expand_args_reply->add_expanded_args(*expanded_arg);
         }
     }
 }
@@ -177,7 +126,7 @@
 
         auto init_message = ReadMessage(init_fd_);
         if (!init_message) {
-            if (init_message.error_errno() == 0) {
+            if (init_message.error().code() == 0) {
                 // If the init file descriptor was closed, let's exit quietly. If
                 // this was accidental, init will restart us. If init died, this
                 // avoids calling abort(3) unnecessarily.
@@ -206,6 +155,11 @@
                            << subcontext_command.command_case();
         }
 
+        if (!shutdown_command.empty()) {
+            reply.set_trigger_shutdown(shutdown_command);
+            shutdown_command.clear();
+        }
+
         if (auto result = SendMessage(init_fd_, reply); !result) {
             LOG(FATAL) << "Failed to send message to init: " << result.error();
         }
@@ -214,7 +168,7 @@
 
 }  // namespace
 
-int SubcontextMain(int argc, char** argv, const KeywordFunctionMap* function_map) {
+int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map) {
     if (argc < 4) LOG(FATAL) << "Fewer than 4 args specified to subcontext (" << argc << ")";
 
     auto context = std::string(argv[2]);
@@ -222,7 +176,7 @@
 
     SelabelInitialize();
 
-    property_set = SubcontextPropertySet;
+    trigger_shutdown = [](const std::string& command) { shutdown_command = command; };
 
     auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
     subcontext_process.MainLoop();
@@ -245,13 +199,17 @@
 
         // We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
         // in the subcontext process after we exec.
-        int child_fd = dup(subcontext_socket);
+        int child_fd = dup(subcontext_socket);  // NOLINT(android-cloexec-dup)
         if (child_fd < 0) {
             PLOG(FATAL) << "Could not dup child_fd";
         }
 
-        if (setexeccon(context_.c_str()) < 0) {
-            PLOG(FATAL) << "Could not set execcon for '" << context_ << "'";
+        // We don't switch contexts if we're running the unit tests.  We don't use std::optional,
+        // since we still need a real context string to pass to the builtin functions.
+        if (context_ != kTestContext) {
+            if (setexeccon(context_.c_str()) < 0) {
+                PLOG(FATAL) << "Could not set execcon for '" << context_ << "'";
+            }
         }
 
         auto init_path = GetExecutablePath();
@@ -278,6 +236,15 @@
     Fork();
 }
 
+bool Subcontext::PathMatchesSubcontext(const std::string& path) {
+    for (const auto& prefix : path_prefixes_) {
+        if (StartsWith(path, prefix)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) {
     if (auto result = SendMessage(socket_, subcontext_command); !result) {
         Restart();
@@ -295,10 +262,15 @@
         Restart();
         return Error() << "Unable to parse message from subcontext";
     }
+
+    if (subcontext_reply.has_trigger_shutdown()) {
+        trigger_shutdown(subcontext_reply.trigger_shutdown());
+    }
+
     return subcontext_reply;
 }
 
-Result<Success> Subcontext::Execute(const std::vector<std::string>& args) {
+Result<void> Subcontext::Execute(const std::vector<std::string>& args) {
     auto subcontext_command = SubcontextCommand();
     std::copy(
         args.begin(), args.end(),
@@ -309,15 +281,6 @@
         return subcontext_reply.error();
     }
 
-    for (const auto& property : subcontext_reply->properties_to_set()) {
-        ucred cr = {.pid = pid_, .uid = 0, .gid = 0};
-        std::string error;
-        if (HandlePropertySet(property.name(), property.value(), context_, cr, &error) != 0) {
-            LOG(ERROR) << "Subcontext init could not set '" << property.name() << "' to '"
-                       << property.value() << "': " << error;
-        }
-    }
-
     if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
         auto& failure = subcontext_reply->failure();
         return ResultError(failure.error_string(), failure.error_errno());
@@ -328,7 +291,7 @@
                        << subcontext_reply->reply_case();
     }
 
-    return Success();
+    return {};
 }
 
 Result<std::vector<std::string>> Subcontext::ExpandArgs(const std::vector<std::string>& args) {
@@ -363,13 +326,12 @@
 static std::vector<Subcontext> subcontexts;
 static bool shutting_down;
 
-std::vector<Subcontext>* InitializeSubcontexts() {
+std::unique_ptr<Subcontext> InitializeSubcontext() {
     if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
-        for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
-            subcontexts.emplace_back(path_prefix, secontext);
-        }
+        return std::make_unique<Subcontext>(std::vector<std::string>{"/vendor", "/odm"},
+                                            kVendorContext);
     }
-    return &subcontexts;
+    return nullptr;
 }
 
 bool SubcontextChildReap(pid_t pid) {
diff --git a/init/subcontext.h b/init/subcontext.h
index 628fd50..5e1d8a8 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_SUBCONTEXT_H
-#define _INIT_SUBCONTEXT_H
+#pragma once
 
 #include <signal.h>
 
@@ -31,22 +30,22 @@
 namespace android {
 namespace init {
 
-extern const std::string kInitContext;
-extern const std::string kVendorContext;
-extern const char* const paths_and_secontexts[2][2];
+static constexpr const char kInitContext[] = "u:r:init:s0";
+static constexpr const char kVendorContext[] = "u:r:vendor_init:s0";
+static constexpr const char kTestContext[] = "test-test-test";
 
 class Subcontext {
   public:
-    Subcontext(std::string path_prefix, std::string context)
-        : path_prefix_(std::move(path_prefix)), context_(std::move(context)), pid_(0) {
+    Subcontext(std::vector<std::string> path_prefixes, std::string context)
+        : path_prefixes_(std::move(path_prefixes)), context_(std::move(context)), pid_(0) {
         Fork();
     }
 
-    Result<Success> Execute(const std::vector<std::string>& args);
+    Result<void> Execute(const std::vector<std::string>& args);
     Result<std::vector<std::string>> ExpandArgs(const std::vector<std::string>& args);
     void Restart();
+    bool PathMatchesSubcontext(const std::string& path);
 
-    const std::string& path_prefix() const { return path_prefix_; }
     const std::string& context() const { return context_; }
     pid_t pid() const { return pid_; }
 
@@ -54,18 +53,16 @@
     void Fork();
     Result<SubcontextReply> TransmitMessage(const SubcontextCommand& subcontext_command);
 
-    std::string path_prefix_;
+    std::vector<std::string> path_prefixes_;
     std::string context_;
     pid_t pid_;
     android::base::unique_fd socket_;
 };
 
-int SubcontextMain(int argc, char** argv, const KeywordFunctionMap* function_map);
-std::vector<Subcontext>* InitializeSubcontexts();
+int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map);
+std::unique_ptr<Subcontext> InitializeSubcontext();
 bool SubcontextChildReap(pid_t pid);
 void SubcontextTerminate();
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/subcontext.proto b/init/subcontext.proto
index c31f4fb..068c7ce 100644
--- a/init/subcontext.proto
+++ b/init/subcontext.proto
@@ -39,9 +39,5 @@
         ExpandArgsReply expand_args_reply = 3;
     }
 
-    message PropertyToSet {
-        optional string name = 1;
-        optional string value = 2;
-    }
-    repeated PropertyToSet properties_to_set = 4;
+    optional string trigger_shutdown = 4;
 }
\ No newline at end of file
diff --git a/init/subcontext_benchmark.cpp b/init/subcontext_benchmark.cpp
index eae03e3..ccef2f3 100644
--- a/init/subcontext_benchmark.cpp
+++ b/init/subcontext_benchmark.cpp
@@ -19,8 +19,6 @@
 #include <benchmark/benchmark.h>
 #include <selinux/selinux.h>
 
-#include "test_function_map.h"
-
 namespace android {
 namespace init {
 
@@ -35,11 +33,11 @@
         return;
     }
 
-    auto subcontext = Subcontext("path", context);
+    auto subcontext = Subcontext({"path"}, context);
     free(context);
 
     while (state.KeepRunning()) {
-        subcontext.Execute(std::vector<std::string>{"return_success"}).IgnoreError();
+        subcontext.Execute(std::vector<std::string>{"return_success"});
     }
 
     if (subcontext.pid() > 0) {
@@ -50,11 +48,11 @@
 
 BENCHMARK(BenchmarkSuccess);
 
-TestFunctionMap BuildTestFunctionMap() {
-    TestFunctionMap test_function_map;
-    test_function_map.Add("return_success", 0, 0, true,
-                          [](const BuiltinArguments& args) { return Success(); });
-
+BuiltinFunctionMap BuildTestFunctionMap() {
+    auto function = [](const BuiltinArguments& args) { return Result<void>{}; };
+    BuiltinFunctionMap test_function_map = {
+            {"return_success", {0, 0, {true, function}}},
+    };
     return test_function_map;
 }
 
diff --git a/init/subcontext_test.cpp b/init/subcontext_test.cpp
index 230203a..2e5a256 100644
--- a/init/subcontext_test.cpp
+++ b/init/subcontext_test.cpp
@@ -26,7 +26,7 @@
 #include <selinux/selinux.h>
 
 #include "builtin_arguments.h"
-#include "test_function_map.h"
+#include "util.h"
 
 using namespace std::literals;
 
@@ -39,24 +39,12 @@
 namespace android {
 namespace init {
 
-// I would use test fixtures, but I cannot skip the test if not root with them, so instead we have
-// this test runner.
 template <typename F>
 void RunTest(F&& test_function) {
-    if (getuid() != 0) {
-        GTEST_LOG_(INFO) << "Skipping test, must be run as root.";
-        return;
-    }
-
-    char* context;
-    ASSERT_EQ(0, getcon(&context));
-    auto context_string = std::string(context);
-    free(context);
-
-    auto subcontext = Subcontext("dummy_path", context_string);
+    auto subcontext = Subcontext({"dummy_path"}, kTestContext);
     ASSERT_NE(0, subcontext.pid());
 
-    test_function(subcontext, context_string);
+    test_function(subcontext);
 
     if (subcontext.pid() > 0) {
         kill(subcontext.pid(), SIGTERM);
@@ -65,11 +53,11 @@
 }
 
 TEST(subcontext, CheckDifferentPid) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    RunTest([](auto& subcontext) {
         auto result = subcontext.Execute(std::vector<std::string>{"return_pids_as_error"});
         ASSERT_FALSE(result);
 
-        auto pids = Split(result.error_string(), " ");
+        auto pids = Split(result.error().message(), " ");
         ASSERT_EQ(2U, pids.size());
         auto our_pid = std::to_string(getpid());
         EXPECT_NE(our_pid, pids[0]);
@@ -78,7 +66,12 @@
 }
 
 TEST(subcontext, SetProp) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Skipping test, must be run as root.";
+        return;
+    }
+
+    RunTest([](auto& subcontext) {
         SetProperty("init.test.subcontext", "fail");
         WaitForProperty("init.test.subcontext", "fail");
 
@@ -95,7 +88,7 @@
 }
 
 TEST(subcontext, MultipleCommands) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    RunTest([](auto& subcontext) {
         auto first_pid = subcontext.pid();
 
         auto expected_words = std::vector<std::string>{
@@ -116,13 +109,13 @@
 
         auto result = subcontext.Execute(std::vector<std::string>{"return_words_as_error"});
         ASSERT_FALSE(result);
-        EXPECT_EQ(Join(expected_words, " "), result.error_string());
+        EXPECT_EQ(Join(expected_words, " "), result.error().message());
         EXPECT_EQ(first_pid, subcontext.pid());
     });
 }
 
 TEST(subcontext, RecoverAfterAbort) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    RunTest([](auto& subcontext) {
         auto first_pid = subcontext.pid();
 
         auto result = subcontext.Execute(std::vector<std::string>{"cause_log_fatal"});
@@ -130,21 +123,33 @@
 
         auto result2 = subcontext.Execute(std::vector<std::string>{"generate_sane_error"});
         ASSERT_FALSE(result2);
-        EXPECT_EQ("Sane error!", result2.error_string());
+        EXPECT_EQ("Sane error!", result2.error().message());
         EXPECT_NE(subcontext.pid(), first_pid);
     });
 }
 
 TEST(subcontext, ContextString) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    RunTest([](auto& subcontext) {
         auto result = subcontext.Execute(std::vector<std::string>{"return_context_as_error"});
         ASSERT_FALSE(result);
-        ASSERT_EQ(context_string, result.error_string());
+        ASSERT_EQ(kTestContext, result.error().message());
     });
 }
 
+TEST(subcontext, TriggerShutdown) {
+    static constexpr const char kTestShutdownCommand[] = "reboot,test-shutdown-command";
+    static std::string trigger_shutdown_command;
+    trigger_shutdown = [](const std::string& command) { trigger_shutdown_command = command; };
+    RunTest([](auto& subcontext) {
+        auto result = subcontext.Execute(
+                std::vector<std::string>{"trigger_shutdown", kTestShutdownCommand});
+        ASSERT_TRUE(result);
+    });
+    EXPECT_EQ(kTestShutdownCommand, trigger_shutdown_command);
+}
+
 TEST(subcontext, ExpandArgs) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    RunTest([](auto& subcontext) {
         auto args = std::vector<std::string>{
             "first",
             "${ro.hardware}",
@@ -160,69 +165,79 @@
 }
 
 TEST(subcontext, ExpandArgsFailure) {
-    RunTest([](auto& subcontext, auto& context_string) {
+    RunTest([](auto& subcontext) {
         auto args = std::vector<std::string>{
             "first",
             "${",
         };
         auto result = subcontext.ExpandArgs(args);
         ASSERT_FALSE(result);
-        EXPECT_EQ("Failed to expand '" + args[1] + "'", result.error_string());
+        EXPECT_EQ("unexpected end of string in '" + args[1] + "', looking for }",
+                  result.error().message());
     });
 }
 
-TestFunctionMap BuildTestFunctionMap() {
-    TestFunctionMap test_function_map;
+BuiltinFunctionMap BuildTestFunctionMap() {
     // For CheckDifferentPid
-    test_function_map.Add("return_pids_as_error", 0, 0, true,
-                          [](const BuiltinArguments& args) -> Result<Success> {
-                              return Error() << getpid() << " " << getppid();
-                          });
+    auto do_return_pids_as_error = [](const BuiltinArguments& args) -> Result<void> {
+        return Error() << getpid() << " " << getppid();
+    };
 
     // For SetProp
-    test_function_map.Add("setprop", 2, 2, true, [](const BuiltinArguments& args) {
+    auto do_setprop = [](const BuiltinArguments& args) {
         android::base::SetProperty(args[1], args[2]);
-        return Success();
-    });
+        return Result<void>{};
+    };
 
     // For MultipleCommands
     // Using a shared_ptr to extend lifetime of words to both lambdas
     auto words = std::make_shared<std::vector<std::string>>();
-    test_function_map.Add("add_word", 1, 1, true, [words](const BuiltinArguments& args) {
+    auto do_add_word = [words](const BuiltinArguments& args) {
         words->emplace_back(args[1]);
-        return Success();
-    });
-    test_function_map.Add("return_words_as_error", 0, 0, true,
-                          [words](const BuiltinArguments& args) -> Result<Success> {
-                              return Error() << Join(*words, " ");
-                          });
+        return Result<void>{};
+    };
+    auto do_return_words_as_error = [words](const BuiltinArguments& args) -> Result<void> {
+        return Error() << Join(*words, " ");
+    };
 
     // For RecoverAfterAbort
-    test_function_map.Add("cause_log_fatal", 0, 0, true,
-                          [](const BuiltinArguments& args) -> Result<Success> {
-                              return Error() << std::string(4097, 'f');
-                          });
-    test_function_map.Add(
-        "generate_sane_error", 0, 0, true,
-        [](const BuiltinArguments& args) -> Result<Success> { return Error() << "Sane error!"; });
+    auto do_cause_log_fatal = [](const BuiltinArguments& args) -> Result<void> {
+        return Error() << std::string(4097, 'f');
+    };
+    auto do_generate_sane_error = [](const BuiltinArguments& args) -> Result<void> {
+        return Error() << "Sane error!";
+    };
 
     // For ContextString
-    test_function_map.Add(
-        "return_context_as_error", 0, 0, true,
-        [](const BuiltinArguments& args) -> Result<Success> { return Error() << args.context; });
+    auto do_return_context_as_error = [](const BuiltinArguments& args) -> Result<void> {
+        return Error() << args.context;
+    };
 
+    auto do_trigger_shutdown = [](const BuiltinArguments& args) -> Result<void> {
+        trigger_shutdown(args[1]);
+        return {};
+    };
+
+    // clang-format off
+    BuiltinFunctionMap test_function_map = {
+        {"return_pids_as_error",        {0,     0,      {true,  do_return_pids_as_error}}},
+        {"setprop",                     {2,     2,      {true,  do_setprop}}},
+        {"add_word",                    {1,     1,      {true,  do_add_word}}},
+        {"return_words_as_error",       {0,     0,      {true,  do_return_words_as_error}}},
+        {"cause_log_fatal",             {0,     0,      {true,  do_cause_log_fatal}}},
+        {"generate_sane_error",         {0,     0,      {true,  do_generate_sane_error}}},
+        {"return_context_as_error",     {0,     0,      {true,  do_return_context_as_error}}},
+        {"trigger_shutdown",            {1,     1,      {true,  do_trigger_shutdown}}},
+    };
+    // clang-format on
     return test_function_map;
 }
 
 }  // namespace init
 }  // namespace android
 
-int main(int argc, char** argv) {
-    if (argc > 1 && !strcmp(basename(argv[1]), "subcontext")) {
-        auto test_function_map = android::init::BuildTestFunctionMap();
-        return android::init::SubcontextMain(argc, argv, &test_function_map);
-    }
-
-    testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
+// init_test.cpp contains the main entry point for all init tests.
+int SubcontextTestChildMain(int argc, char** argv) {
+    auto test_function_map = android::init::BuildTestFunctionMap();
+    return android::init::SubcontextMain(argc, argv, &test_function_map);
 }
diff --git a/init/sysprop/Android.bp b/init/sysprop/Android.bp
new file mode 100644
index 0000000..7582875
--- /dev/null
+++ b/init/sysprop/Android.bp
@@ -0,0 +1,7 @@
+sysprop_library {
+  name: "com.android.sysprop.init",
+  srcs: ["InitProperties.sysprop"],
+  property_owner: "Platform",
+  api_packages: ["android.sysprop"],
+  recovery_available: true,
+}
diff --git a/init/sysprop/InitProperties.sysprop b/init/sysprop/InitProperties.sysprop
new file mode 100644
index 0000000..c856358
--- /dev/null
+++ b/init/sysprop/InitProperties.sysprop
@@ -0,0 +1,36 @@
+# 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.
+
+owner: Platform
+module: "android.sysprop.InitProperties"
+
+# Serves as a signal to all processes that userspace reboot is happening.
+prop {
+    api_name: "userspace_reboot_in_progress"
+    type: Boolean
+    scope: Public
+    access: ReadWrite
+    prop_name: "sys.init.userspace_reboot.in_progress"
+    integer_as_bool: true
+}
+
+# Shows whenever the device supports userspace reboot or not.
+prop {
+    api_name: "is_userspace_reboot_supported"
+    type: Boolean
+    scope: System
+    access: Readonly
+    prop_name: "ro.init.userspace_reboot.is_supported"
+    integer_as_bool: true
+}
diff --git a/init/sysprop/api/com.android.sysprop.init-current.txt b/init/sysprop/api/com.android.sysprop.init-current.txt
new file mode 100644
index 0000000..b8bcef9
--- /dev/null
+++ b/init/sysprop/api/com.android.sysprop.init-current.txt
@@ -0,0 +1,14 @@
+props {
+  module: "android.sysprop.InitProperties"
+  prop {
+    api_name: "is_userspace_reboot_supported"
+    prop_name: "ro.init.userspace_reboot.is_supported"
+    integer_as_bool: true
+  }
+  prop {
+    api_name: "userspace_reboot_in_progress"
+    access: ReadWrite
+    prop_name: "sys.init.userspace_reboot.in_progress"
+    integer_as_bool: true
+  }
+}
diff --git a/init/sysprop/api/com.android.sysprop.init-latest.txt b/init/sysprop/api/com.android.sysprop.init-latest.txt
new file mode 100644
index 0000000..c835b95
--- /dev/null
+++ b/init/sysprop/api/com.android.sysprop.init-latest.txt
@@ -0,0 +1,9 @@
+props {
+  module: "android.sysprop.InitProperties"
+  prop {
+    api_name: "userspace_reboot_in_progress"
+    scope: Public
+    prop_name: "sys.init.userspace_reboot.in_progress"
+    integer_as_bool: true
+  }
+}
diff --git a/init/test_function_map.h b/init/test_function_map.h
deleted file mode 100644
index 583df1a..0000000
--- a/init/test_function_map.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 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 _INIT_TEST_FUNCTION_MAP_H
-#define _INIT_TEST_FUNCTION_MAP_H
-
-#include <string>
-#include <vector>
-
-#include "builtin_arguments.h"
-#include "keyword_map.h"
-
-namespace android {
-namespace init {
-
-class TestFunctionMap : public KeywordFunctionMap {
-  public:
-    // Helper for argument-less functions
-    using BuiltinFunctionNoArgs = std::function<void(void)>;
-    void Add(const std::string& name, const BuiltinFunctionNoArgs function) {
-        Add(name, 0, 0, false, [function](const BuiltinArguments&) {
-            function();
-            return Success();
-        });
-    }
-
-    void Add(const std::string& name, std::size_t min_parameters, std::size_t max_parameters,
-             bool run_in_subcontext, const BuiltinFunction function) {
-        builtin_functions_[name] =
-            make_tuple(min_parameters, max_parameters, make_pair(run_in_subcontext, function));
-    }
-
-  private:
-    Map builtin_functions_ = {};
-
-    const Map& map() const override { return builtin_functions_; }
-};
-
-}  // namespace init
-}  // namespace android
-
-#endif
diff --git a/init/test_utils/Android.bp b/init/test_utils/Android.bp
new file mode 100644
index 0000000..1cb05b6
--- /dev/null
+++ b/init/test_utils/Android.bp
@@ -0,0 +1,27 @@
+cc_library_static {
+    name: "libinit_test_utils",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Wno-unused-parameter",
+        "-Werror",
+    ],
+    srcs: [
+        "service_utils.cpp",
+    ],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libjsoncpp",
+        "libprotobuf-cpp-lite",
+        "libhidl-gen-utils",
+    ],
+    whole_static_libs: [
+        "libinit",
+        "libpropertyinfoparser",
+    ],
+    static_libs: [
+        "libbase",
+    ],
+    export_include_dirs: ["include"], // for tests
+}
diff --git a/libmeminfo/libdmabufinfo/tools/Android.bp b/init/test_utils/include/init-test-utils/service_utils.h
similarity index 62%
copy from libmeminfo/libdmabufinfo/tools/Android.bp
copy to init/test_utils/include/init-test-utils/service_utils.h
index 224b68e..3ec61d4 100644
--- a/libmeminfo/libdmabufinfo/tools/Android.bp
+++ b/init/test_utils/include/init-test-utils/service_utils.h
@@ -1,3 +1,4 @@
+//
 // Copyright (C) 2019 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -11,20 +12,21 @@
 // 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_binary {
-    name: "dmabuf_dump",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
+#pragma once
 
-    srcs: ["dmabuf_dump.cpp"],
-    shared_libs: [
-        "libbase",
-    ],
-    static_libs: [
-        "libdmabufinfo",
-    ],
-    product_specific: true,
-}
\ No newline at end of file
+#include <map>
+#include <set>
+
+#include <android-base/result.h>
+#include <hidl-util/FqInstance.h>
+
+namespace android {
+namespace init {
+
+using ServiceInterfacesMap = std::map<std::string, std::set<android::FqInstance>>;
+android::base::Result<ServiceInterfacesMap> GetOnDeviceServiceInterfacesMap();
+
+}  // namespace init
+}  // namespace android
diff --git a/init/test_utils/service_utils.cpp b/init/test_utils/service_utils.cpp
new file mode 100644
index 0000000..bc00702
--- /dev/null
+++ b/init/test_utils/service_utils.cpp
@@ -0,0 +1,63 @@
+//
+// 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 <string>
+
+#include <android-base/logging.h>
+
+#include "../parser.h"
+#include "../service.h"
+#include "../service_list.h"
+#include "../service_parser.h"
+#include "include/init-test-utils/service_utils.h"
+
+namespace android {
+namespace init {
+
+android::base::Result<ServiceInterfacesMap> GetOnDeviceServiceInterfacesMap() {
+    ServiceList& service_list = ServiceList::GetInstance();
+    Parser parser;
+    parser.AddSectionParser("service",
+                            std::make_unique<ServiceParser>(&service_list, nullptr, std::nullopt));
+    for (const auto& location : {
+                 "/init.rc",
+                 "/system/etc/init",
+                 "/system_ext/etc/init",
+                 "/product/etc/init",
+                 "/odm/etc/init",
+                 "/vendor/etc/init",
+         }) {
+        parser.ParseConfig(location);
+    }
+
+    ServiceInterfacesMap result;
+    for (const auto& service : service_list.services()) {
+        // Create an entry for all services, including services that may not
+        // have any declared interfaces.
+        result[service->name()] = std::set<android::FqInstance>();
+        for (const auto& intf : service->interfaces()) {
+            android::FqInstance fqInstance;
+            if (!fqInstance.setTo(intf)) {
+                return android::base::Error() << "Unable to parse interface: '" << intf << "'";
+            }
+            result[service->name()].insert(fqInstance);
+        }
+    }
+    return result;
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/tokenizer_test.cpp b/init/tokenizer_test.cpp
index acfc7c7..6b31683 100644
--- a/init/tokenizer_test.cpp
+++ b/init/tokenizer_test.cpp
@@ -46,6 +46,7 @@
                 return;
             case T_NEWLINE:
                 tokens.emplace_back(std::move(current_line));
+                current_line.clear();
                 break;
             case T_TEXT:
                 current_line.emplace_back(state.text);
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 62cd2be..d8d9b36 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -100,7 +100,7 @@
     int n = uevent_kernel_multicast_recv(device_fd_, msg, UEVENT_MSG_LEN);
     if (n <= 0) {
         if (errno != EAGAIN && errno != EWOULDBLOCK) {
-            LOG(ERROR) << "Error reading from Uevent Fd";
+            PLOG(ERROR) << "Error reading from Uevent Fd";
         }
         return false;
     }
@@ -131,7 +131,7 @@
                                                        const ListenerCallback& callback) const {
     int dfd = dirfd(d);
 
-    int fd = openat(dfd, "uevent", O_WRONLY);
+    int fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC);
     if (fd >= 0) {
         write(fd, "add\n", 4);
         close(fd);
@@ -146,7 +146,7 @@
     while ((de = readdir(d)) != nullptr) {
         if (de->d_type != DT_DIR || de->d_name[0] == '.') continue;
 
-        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
         if (fd < 0) continue;
 
         std::unique_ptr<DIR, decltype(&closedir)> d2(fdopendir(fd), closedir);
@@ -171,7 +171,7 @@
     return RegenerateUeventsForDir(d.get(), callback);
 }
 
-static const char* kRegenerationPaths[] = {"/sys/class", "/sys/block", "/sys/devices"};
+static const char* kRegenerationPaths[] = {"/sys/devices"};
 
 void UeventListener::RegenerateUevents(const ListenerCallback& callback) const {
     for (const auto path : kRegenerationPaths) {
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 399ea4c..d2b503b 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -17,12 +17,15 @@
 #include "ueventd.h"
 
 #include <ctype.h>
+#include <dirent.h>
 #include <fcntl.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <set>
 #include <thread>
@@ -37,6 +40,7 @@
 #include "devices.h"
 #include "firmware_handler.h"
 #include "modalias_handler.h"
+#include "selabel.h"
 #include "selinux.h"
 #include "uevent_handler.h"
 #include "uevent_listener.h"
@@ -109,10 +113,12 @@
 class ColdBoot {
   public:
     ColdBoot(UeventListener& uevent_listener,
-             std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers)
+             std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers,
+             bool enable_parallel_restorecon)
         : uevent_listener_(uevent_listener),
           uevent_handlers_(uevent_handlers),
-          num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4) {}
+          num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4),
+          enable_parallel_restorecon_(enable_parallel_restorecon) {}
 
     void Run();
 
@@ -120,16 +126,21 @@
     void UeventHandlerMain(unsigned int process_num, unsigned int total_processes);
     void RegenerateUevents();
     void ForkSubProcesses();
-    void DoRestoreCon();
     void WaitForSubProcesses();
+    void RestoreConHandler(unsigned int process_num, unsigned int total_processes);
+    void GenerateRestoreCon(const std::string& directory);
 
     UeventListener& uevent_listener_;
     std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers_;
 
     unsigned int num_handler_subprocesses_;
+    bool enable_parallel_restorecon_;
+
     std::vector<Uevent> uevent_queue_;
 
     std::set<pid_t> subprocess_pids_;
+
+    std::vector<std::string> restorecon_queue_;
 };
 
 void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_processes) {
@@ -140,12 +151,40 @@
             uevent_handler->HandleUevent(uevent);
         }
     }
-    _exit(EXIT_SUCCESS);
+}
+
+void ColdBoot::RestoreConHandler(unsigned int process_num, unsigned int total_processes) {
+    for (unsigned int i = process_num; i < restorecon_queue_.size(); i += total_processes) {
+        auto& dir = restorecon_queue_[i];
+
+        selinux_android_restorecon(dir.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
+    }
+}
+
+void ColdBoot::GenerateRestoreCon(const std::string& directory) {
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(directory.c_str()), &closedir);
+
+    if (!dir) return;
+
+    struct dirent* dent;
+    while ((dent = readdir(dir.get())) != NULL) {
+        if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue;
+
+        struct stat st;
+        if (fstatat(dirfd(dir.get()), dent->d_name, &st, 0) == -1) continue;
+
+        if (S_ISDIR(st.st_mode)) {
+            std::string fullpath = directory + "/" + dent->d_name;
+            if (fullpath != "/sys/devices") {
+                restorecon_queue_.emplace_back(fullpath);
+            }
+        }
+    }
 }
 
 void ColdBoot::RegenerateUevents() {
     uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {
-        uevent_queue_.emplace_back(std::move(uevent));
+        uevent_queue_.emplace_back(uevent);
         return ListenerAction::kContinue;
     });
 }
@@ -159,16 +198,16 @@
 
         if (pid == 0) {
             UeventHandlerMain(i, num_handler_subprocesses_);
+            if (enable_parallel_restorecon_) {
+                RestoreConHandler(i, num_handler_subprocesses_);
+            }
+            _exit(EXIT_SUCCESS);
         }
 
         subprocess_pids_.emplace(pid);
     }
 }
 
-void ColdBoot::DoRestoreCon() {
-    selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
-}
-
 void ColdBoot::WaitForSubProcesses() {
     // Treat subprocesses that crash or get stuck the same as if ueventd itself has crashed or gets
     // stuck.
@@ -207,13 +246,23 @@
 
     RegenerateUevents();
 
+    if (enable_parallel_restorecon_) {
+        selinux_android_restorecon("/sys", 0);
+        selinux_android_restorecon("/sys/devices", 0);
+        GenerateRestoreCon("/sys");
+        // takes long time for /sys/devices, parallelize it
+        GenerateRestoreCon("/sys/devices");
+    }
+
     ForkSubProcesses();
 
-    DoRestoreCon();
+    if (!enable_parallel_restorecon_) {
+        selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
+    }
 
     WaitForSubProcesses();
 
-    close(open(COLDBOOT_DONE, O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
+    android::base::SetProperty(kColdBootDoneProp, "true");
     LOG(INFO) << "Coldboot took " << cold_boot_timer.duration().count() / 1000.0f << " seconds";
 }
 
@@ -239,7 +288,7 @@
     // TODO: cleanup platform ueventd.rc to remove vendor specific device node entries (b/34968103)
     auto hardware = android::base::GetProperty("ro.hardware", "");
 
-    auto ueventd_configuration = ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc",
+    auto ueventd_configuration = ParseConfig({"/system/etc/ueventd.rc", "/vendor/ueventd.rc",
                                               "/odm/ueventd.rc", "/ueventd." + hardware + ".rc"});
 
     uevent_handlers.emplace_back(std::make_unique<DeviceHandler>(
@@ -247,15 +296,18 @@
             std::move(ueventd_configuration.sysfs_permissions),
             std::move(ueventd_configuration.subsystems), android::fs_mgr::GetBootDevices(), true));
     uevent_handlers.emplace_back(std::make_unique<FirmwareHandler>(
-            std::move(ueventd_configuration.firmware_directories)));
+            std::move(ueventd_configuration.firmware_directories),
+            std::move(ueventd_configuration.external_firmware_handlers)));
 
     if (ueventd_configuration.enable_modalias_handling) {
-        uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>());
+        std::vector<std::string> base_paths = {"/odm/lib/modules", "/vendor/lib/modules"};
+        uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>(base_paths));
     }
     UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size);
 
-    if (access(COLDBOOT_DONE, F_OK) != 0) {
-        ColdBoot cold_boot(uevent_listener, uevent_handlers);
+    if (!android::base::GetBoolProperty(kColdBootDoneProp, false)) {
+        ColdBoot cold_boot(uevent_listener, uevent_handlers,
+                           ueventd_configuration.enable_parallel_restorecon);
         cold_boot.Run();
     }
 
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index aac3fe5..a74b247 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -29,9 +29,9 @@
 namespace android {
 namespace init {
 
-Result<Success> ParsePermissionsLine(std::vector<std::string>&& args,
-                                     std::vector<SysfsPermissions>* out_sysfs_permissions,
-                                     std::vector<Permissions>* out_dev_permissions) {
+Result<void> ParsePermissionsLine(std::vector<std::string>&& args,
+                                  std::vector<SysfsPermissions>* out_sysfs_permissions,
+                                  std::vector<Permissions>* out_dev_permissions) {
     bool is_sysfs = out_sysfs_permissions != nullptr;
     if (is_sysfs && args.size() != 5) {
         return Error() << "/sys/ lines must have 5 entries";
@@ -74,39 +74,63 @@
     } else {
         out_dev_permissions->emplace_back(name, perm, uid, gid);
     }
-    return Success();
+    return {};
 }
 
-Result<Success> ParseFirmwareDirectoriesLine(std::vector<std::string>&& args,
-                                             std::vector<std::string>* firmware_directories) {
+Result<void> ParseFirmwareDirectoriesLine(std::vector<std::string>&& args,
+                                          std::vector<std::string>* firmware_directories) {
     if (args.size() < 2) {
         return Error() << "firmware_directories must have at least 1 entry";
     }
 
     std::move(std::next(args.begin()), args.end(), std::back_inserter(*firmware_directories));
 
-    return Success();
+    return {};
 }
 
-Result<Success> ParseModaliasHandlingLine(std::vector<std::string>&& args,
-                                          bool* enable_modalias_handling) {
+Result<void> ParseExternalFirmwareHandlerLine(
+        std::vector<std::string>&& args,
+        std::vector<ExternalFirmwareHandler>* external_firmware_handlers) {
+    if (args.size() != 4) {
+        return Error() << "external_firmware_handler lines must have exactly 3 parameters";
+    }
+
+    if (std::find_if(external_firmware_handlers->begin(), external_firmware_handlers->end(),
+                     [&args](const auto& other) { return other.devpath == args[2]; }) !=
+        external_firmware_handlers->end()) {
+        return Error() << "found a previous external_firmware_handler with the same devpath, '"
+                       << args[2] << "'";
+    }
+
+    passwd* pwd = getpwnam(args[2].c_str());
+    if (!pwd) {
+        return ErrnoError() << "invalid handler uid'" << args[2] << "'";
+    }
+
+    ExternalFirmwareHandler handler(std::move(args[1]), pwd->pw_uid, std::move(args[3]));
+    external_firmware_handlers->emplace_back(std::move(handler));
+
+    return {};
+}
+
+Result<void> ParseEnabledDisabledLine(std::vector<std::string>&& args, bool* feature) {
     if (args.size() != 2) {
-        return Error() << "modalias_handling lines take exactly one parameter";
+        return Error() << args[0] << " lines take exactly one parameter";
     }
 
     if (args[1] == "enabled") {
-        *enable_modalias_handling = true;
+        *feature = true;
     } else if (args[1] == "disabled") {
-        *enable_modalias_handling = false;
+        *feature = false;
     } else {
-        return Error() << "modalias_handling takes either 'enabled' or 'disabled' as a parameter";
+        return Error() << args[0] << " takes either 'enabled' or 'disabled' as a parameter";
     }
 
-    return Success();
+    return {};
 }
 
-Result<Success> ParseUeventSocketRcvbufSizeLine(std::vector<std::string>&& args,
-                                                size_t* uevent_socket_rcvbuf_size) {
+Result<void> ParseUeventSocketRcvbufSizeLine(std::vector<std::string>&& args,
+                                             size_t* uevent_socket_rcvbuf_size) {
     if (args.size() != 2) {
         return Error() << "uevent_socket_rcvbuf_size lines take exactly one parameter";
     }
@@ -118,27 +142,27 @@
 
     *uevent_socket_rcvbuf_size = parsed_size;
 
-    return Success();
+    return {};
 }
 
 class SubsystemParser : public SectionParser {
   public:
     SubsystemParser(std::vector<Subsystem>* subsystems) : subsystems_(subsystems) {}
-    Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
-                                 int line) override;
-    Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
-    Result<Success> EndSection() override;
+    Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
+                              int line) override;
+    Result<void> ParseLineSection(std::vector<std::string>&& args, int line) override;
+    Result<void> EndSection() override;
 
   private:
-    Result<Success> ParseDevName(std::vector<std::string>&& args);
-    Result<Success> ParseDirName(std::vector<std::string>&& args);
+    Result<void> ParseDevName(std::vector<std::string>&& args);
+    Result<void> ParseDirName(std::vector<std::string>&& args);
 
     Subsystem subsystem_;
     std::vector<Subsystem>* subsystems_;
 };
 
-Result<Success> SubsystemParser::ParseSection(std::vector<std::string>&& args,
-                                              const std::string& filename, int line) {
+Result<void> SubsystemParser::ParseSection(std::vector<std::string>&& args,
+                                           const std::string& filename, int line) {
     if (args.size() != 2) {
         return Error() << "subsystems must have exactly one name";
     }
@@ -149,58 +173,51 @@
 
     subsystem_ = Subsystem(std::move(args[1]));
 
-    return Success();
+    return {};
 }
 
-Result<Success> SubsystemParser::ParseDevName(std::vector<std::string>&& args) {
+Result<void> SubsystemParser::ParseDevName(std::vector<std::string>&& args) {
     if (args[1] == "uevent_devname") {
         subsystem_.devname_source_ = Subsystem::DEVNAME_UEVENT_DEVNAME;
-        return Success();
+        return {};
     }
     if (args[1] == "uevent_devpath") {
         subsystem_.devname_source_ = Subsystem::DEVNAME_UEVENT_DEVPATH;
-        return Success();
+        return {};
     }
 
     return Error() << "invalid devname '" << args[1] << "'";
 }
 
-Result<Success> SubsystemParser::ParseDirName(std::vector<std::string>&& args) {
+Result<void> SubsystemParser::ParseDirName(std::vector<std::string>&& args) {
     if (args[1].front() != '/') {
         return Error() << "dirname '" << args[1] << " ' does not start with '/'";
     }
 
     subsystem_.dir_name_ = args[1];
-    return Success();
+    return {};
 }
 
-Result<Success> SubsystemParser::ParseLineSection(std::vector<std::string>&& args, int line) {
-    using OptionParser = Result<Success> (SubsystemParser::*)(std::vector<std::string> && args);
+Result<void> SubsystemParser::ParseLineSection(std::vector<std::string>&& args, int line) {
+    using OptionParser = Result<void> (SubsystemParser::*)(std::vector<std::string> && args);
+    // clang-format off
+    static const KeywordMap<OptionParser> parser_map = {
+        {"devname",     {1,     1,      &SubsystemParser::ParseDevName}},
+        {"dirname",     {1,     1,      &SubsystemParser::ParseDirName}},
+    };
+    // clang-format on
 
-    static class OptionParserMap : public KeywordMap<OptionParser> {
-      private:
-        const Map& map() const override {
-            // clang-format off
-            static const Map option_parsers = {
-                {"devname",     {1,     1,      &SubsystemParser::ParseDevName}},
-                {"dirname",     {1,     1,      &SubsystemParser::ParseDirName}},
-            };
-            // clang-format on
-            return option_parsers;
-        }
-    } parser_map;
-
-    auto parser = parser_map.FindFunction(args);
+    auto parser = parser_map.Find(args);
 
     if (!parser) return Error() << parser.error();
 
     return std::invoke(*parser, this, std::move(args));
 }
 
-Result<Success> SubsystemParser::EndSection() {
+Result<void> SubsystemParser::EndSection() {
     subsystems_->emplace_back(std::move(subsystem_));
 
-    return Success();
+    return {};
 }
 
 UeventdConfiguration ParseConfig(const std::vector<std::string>& configs) {
@@ -219,12 +236,18 @@
     parser.AddSingleLineParser("firmware_directories",
                                std::bind(ParseFirmwareDirectoriesLine, _1,
                                          &ueventd_configuration.firmware_directories));
+    parser.AddSingleLineParser("external_firmware_handler",
+                               std::bind(ParseExternalFirmwareHandlerLine, _1,
+                                         &ueventd_configuration.external_firmware_handlers));
     parser.AddSingleLineParser("modalias_handling",
-                               std::bind(ParseModaliasHandlingLine, _1,
+                               std::bind(ParseEnabledDisabledLine, _1,
                                          &ueventd_configuration.enable_modalias_handling));
     parser.AddSingleLineParser("uevent_socket_rcvbuf_size",
                                std::bind(ParseUeventSocketRcvbufSizeLine, _1,
                                          &ueventd_configuration.uevent_socket_rcvbuf_size));
+    parser.AddSingleLineParser("parallel_restorecon",
+                               std::bind(ParseEnabledDisabledLine, _1,
+                                         &ueventd_configuration.enable_parallel_restorecon));
 
     for (const auto& config : configs) {
         parser.ParseConfig(config);
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index d476dec..eaafa5a 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_UEVENTD_PARSER_H
-#define _INIT_UEVENTD_PARSER_H
+#pragma once
 
 #include <string>
 #include <vector>
 
 #include "devices.h"
+#include "firmware_handler.h"
 
 namespace android {
 namespace init {
@@ -30,13 +30,13 @@
     std::vector<SysfsPermissions> sysfs_permissions;
     std::vector<Permissions> dev_permissions;
     std::vector<std::string> firmware_directories;
+    std::vector<ExternalFirmwareHandler> external_firmware_handlers;
     bool enable_modalias_handling = false;
     size_t uevent_socket_rcvbuf_size = 0;
+    bool enable_parallel_restorecon = false;
 };
 
 UeventdConfiguration ParseConfig(const std::vector<std::string>& configs);
 
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp
index 9c1cedf..172ba0b 100644
--- a/init/ueventd_parser_test.cpp
+++ b/init/ueventd_parser_test.cpp
@@ -20,6 +20,8 @@
 #include <gtest/gtest.h>
 #include <private/android_filesystem_config.h>
 
+#include "firmware_handler.h"
+
 namespace android {
 namespace init {
 
@@ -93,7 +95,7 @@
             {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
             {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
 
-    TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}});
+    TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}});
 }
 
 TEST(ueventd_parser, Permissions) {
@@ -119,7 +121,7 @@
             {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT},
     };
 
-    TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}});
+    TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}, {}});
 }
 
 TEST(ueventd_parser, FirmwareDirectories) {
@@ -135,7 +137,52 @@
             "/more",
     };
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories, {}});
+}
+
+TEST(ueventd_parser, ExternalFirmwareHandlers) {
+    auto ueventd_file = R"(
+external_firmware_handler devpath root handler_path
+external_firmware_handler /devices/path/firmware/something001.bin system /vendor/bin/firmware_handler.sh
+external_firmware_handler /devices/path/firmware/something001.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
+)";
+
+    auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
+            {
+                    "devpath",
+                    AID_ROOT,
+                    "handler_path",
+            },
+            {
+                    "/devices/path/firmware/something001.bin",
+                    AID_SYSTEM,
+                    "/vendor/bin/firmware_handler.sh",
+            },
+            {
+                    "/devices/path/firmware/something001.bin",
+                    AID_RADIO,
+                    "/vendor/bin/firmware_handler.sh --has --arguments",
+            },
+    };
+
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
+}
+
+TEST(ueventd_parser, ExternalFirmwareHandlersDuplicate) {
+    auto ueventd_file = R"(
+external_firmware_handler devpath root handler_path
+external_firmware_handler devpath root handler_path2
+)";
+
+    auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
+            {
+                    "devpath",
+                    AID_ROOT,
+                    "handler_path",
+            },
+    };
+
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
 }
 
 TEST(ueventd_parser, UeventSocketRcvbufSize) {
@@ -144,7 +191,25 @@
 uevent_socket_rcvbuf_size 8M
 )";
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 8 * 1024 * 1024});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
+}
+
+TEST(ueventd_parser, EnabledDisabledLines) {
+    auto ueventd_file = R"(
+modalias_handling enabled
+parallel_restorecon enabled
+modalias_handling disabled
+)";
+
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, false, 0, true});
+
+    auto ueventd_file2 = R"(
+parallel_restorecon enabled
+modalias_handling enabled
+parallel_restorecon disabled
+)";
+
+    TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, true, 0, false});
 }
 
 TEST(ueventd_parser, AllTogether) {
@@ -178,7 +243,11 @@
 /sys/devices/virtual/*/input   poll_delay  0660  root   input
 firmware_directories /more
 
+external_firmware_handler /devices/path/firmware/firmware001.bin root /vendor/bin/touch.sh
+
 uevent_socket_rcvbuf_size 6M
+modalias_handling enabled
+parallel_restorecon enabled
 
 #ending comment
 )";
@@ -208,10 +277,15 @@
             "/more",
     };
 
+    auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
+            {"/devices/path/firmware/firmware001.bin", AID_ROOT, "/vendor/bin/touch.sh"},
+    };
+
     size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
 
-    TestUeventdFile(ueventd_file, {subsystems, sysfs_permissions, permissions, firmware_directories,
-                                   false, uevent_socket_rcvbuf_size});
+    TestUeventdFile(ueventd_file,
+                    {subsystems, sysfs_permissions, permissions, firmware_directories,
+                     external_firmware_handlers, true, uevent_socket_rcvbuf_size, true});
 }
 
 // All of these lines are ill-formed, so test that there is 0 output.
@@ -230,6 +304,18 @@
 
 subsystem #no name
 
+modalias_handling
+modalias_handling enabled enabled
+modalias_handling blah
+
+parallel_restorecon
+parallel_restorecon enabled enabled
+parallel_restorecon blah
+
+external_firmware_handler
+external_firmware_handler blah blah
+external_firmware_handler blah blah blah blah
+
 )";
 
     TestUeventdFile(ueventd_file, {});
diff --git a/init/ueventd_test.cpp b/init/ueventd_test.cpp
index bfdc28e..2d7d2f8 100644
--- a/init/ueventd_test.cpp
+++ b/init/ueventd_test.cpp
@@ -68,7 +68,7 @@
 
 TEST(ueventd, setegid_IsPerThread) {
     if (getuid() != 0) {
-        GTEST_LOG_(INFO) << "Skipping test, must be run as root.";
+        GTEST_SKIP() << "Skipping test, must be run as root.";
         return;
     }
 
@@ -92,11 +92,11 @@
 
 TEST(ueventd, setfscreatecon_IsPerThread) {
     if (getuid() != 0) {
-        GTEST_LOG_(INFO) << "Skipping test, must be run as root.";
+        GTEST_SKIP() << "Skipping test, must be run as root.";
         return;
     }
     if (!is_selinux_enabled() || security_getenforce() == 1) {
-        GTEST_LOG_(INFO) << "Skipping test, SELinux must be enabled and in permissive mode.";
+        GTEST_SKIP() << "Skipping test, SELinux must be enabled and in permissive mode.";
         return;
     }
 
@@ -127,7 +127,7 @@
 
 TEST(ueventd, selabel_lookup_MultiThreaded) {
     if (getuid() != 0) {
-        GTEST_LOG_(INFO) << "Skipping test, must be run as root.";
+        GTEST_SKIP() << "Skipping test, must be run as root.";
         return;
     }
 
diff --git a/init/util.cpp b/init/util.cpp
index 63d2d44..0ca0da5 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <pwd.h>
+#include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,23 +35,25 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <android-base/scopeguard.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <cutils/sockets.h>
 #include <selinux/android.h>
 
 #if defined(__ANDROID__)
+#include <android/api-level.h>
+#include <sys/system_properties.h>
+
 #include "reboot_utils.h"
+#include "selabel.h"
 #include "selinux.h"
 #else
 #include "host_init_stubs.h"
 #endif
 
-#ifdef _INIT_INIT_H
-#error "Do not include init.h in files used by ueventd; it will expose init's globals"
-#endif
-
 using android::base::boot_clock;
+using android::base::StartsWith;
 using namespace std::literals::string_literals;
 
 namespace android {
@@ -58,6 +61,8 @@
 
 const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android/");
 
+void (*trigger_shutdown)(const std::string& command) = nullptr;
+
 // DecodeUid() - decodes and returns the given string, which can be either the
 // numeric or name representation, into the integer uid or gid.
 Result<uid_t> DecodeUid(const std::string& name) {
@@ -81,32 +86,28 @@
  * daemon. We communicate the file descriptor's value via the environment
  * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
  */
-int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid,
-                 const char* socketcon) {
-    if (socketcon) {
-        if (setsockcreatecon(socketcon) == -1) {
-            PLOG(ERROR) << "setsockcreatecon(\"" << socketcon << "\") failed";
-            return -1;
+Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
+                         gid_t gid, const std::string& socketcon) {
+    if (!socketcon.empty()) {
+        if (setsockcreatecon(socketcon.c_str()) == -1) {
+            return ErrnoError() << "setsockcreatecon(\"" << socketcon << "\") failed";
         }
     }
 
     android::base::unique_fd fd(socket(PF_UNIX, type, 0));
     if (fd < 0) {
-        PLOG(ERROR) << "Failed to open socket '" << name << "'";
-        return -1;
+        return ErrnoError() << "Failed to open socket '" << name << "'";
     }
 
-    if (socketcon) setsockcreatecon(NULL);
+    if (!socketcon.empty()) setsockcreatecon(nullptr);
 
     struct sockaddr_un addr;
     memset(&addr, 0 , sizeof(addr));
     addr.sun_family = AF_UNIX;
-    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
-             name);
+    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR "/%s", name.c_str());
 
     if ((unlink(addr.sun_path) != 0) && (errno != ENOENT)) {
-        PLOG(ERROR) << "Failed to unlink old socket '" << name << "'";
-        return -1;
+        return ErrnoError() << "Failed to unlink old socket '" << name << "'";
     }
 
     std::string secontext;
@@ -117,8 +118,7 @@
     if (passcred) {
         int on = 1;
         if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
-            PLOG(ERROR) << "Failed to set SO_PASSCRED '" << name << "'";
-            return -1;
+            return ErrnoError() << "Failed to set SO_PASSCRED '" << name << "'";
         }
     }
 
@@ -129,19 +129,18 @@
         setfscreatecon(nullptr);
     }
 
+    auto guard = android::base::make_scope_guard([&addr] { unlink(addr.sun_path); });
+
     if (ret) {
         errno = savederrno;
-        PLOG(ERROR) << "Failed to bind socket '" << name << "'";
-        goto out_unlink;
+        return ErrnoError() << "Failed to bind socket '" << name << "'";
     }
 
     if (lchown(addr.sun_path, uid, gid)) {
-        PLOG(ERROR) << "Failed to lchown socket '" << addr.sun_path << "'";
-        goto out_unlink;
+        return ErrnoError() << "Failed to lchown socket '" << addr.sun_path << "'";
     }
     if (fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW)) {
-        PLOG(ERROR) << "Failed to fchmodat socket '" << addr.sun_path << "'";
-        goto out_unlink;
+        return ErrnoError() << "Failed to fchmodat socket '" << addr.sun_path << "'";
     }
 
     LOG(INFO) << "Created socket '" << addr.sun_path << "'"
@@ -149,11 +148,8 @@
               << ", user " << uid
               << ", group " << gid;
 
+    guard.Disable();
     return fd.release();
-
-out_unlink:
-    unlink(addr.sun_path);
-    return -1;
 }
 
 Result<std::string> ReadFile(const std::string& path) {
@@ -197,7 +193,7 @@
     return rc;
 }
 
-Result<Success> WriteFile(const std::string& path, const std::string& content) {
+Result<void> WriteFile(const std::string& path, const std::string& content) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(
         OpenFile(path, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
     if (fd == -1) {
@@ -206,7 +202,7 @@
     if (!android::base::WriteStringToFd(content, fd)) {
         return ErrnoError() << "Unable to write file contents";
     }
-    return Success();
+    return {};
 }
 
 bool mkdir_recursive(const std::string& path, mode_t mode) {
@@ -238,15 +234,14 @@
     return -1;
 }
 
-void import_kernel_cmdline(bool in_qemu,
-                           const std::function<void(const std::string&, const std::string&, bool)>& fn) {
+void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>& fn) {
     std::string cmdline;
     android::base::ReadFileToString("/proc/cmdline", &cmdline);
 
     for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
         std::vector<std::string> pieces = android::base::Split(entry, "=");
         if (pieces.size() == 2) {
-            fn(pieces[0], pieces[1], in_qemu);
+            fn(pieces[0], pieces[1]);
         }
     }
 }
@@ -279,12 +274,10 @@
     return S_ISDIR(info.st_mode);
 }
 
-bool expand_props(const std::string& src, std::string* dst) {
+Result<std::string> ExpandProps(const std::string& src) {
     const char* src_ptr = src.c_str();
 
-    if (!dst) {
-        return false;
-    }
+    std::string dst;
 
     /* - variables can either be $x.y or ${x.y}, in case they are only part
      *   of the string.
@@ -298,19 +291,19 @@
 
         c = strchr(src_ptr, '$');
         if (!c) {
-            dst->append(src_ptr);
-            return true;
+            dst.append(src_ptr);
+            return dst;
         }
 
-        dst->append(src_ptr, c);
+        dst.append(src_ptr, c);
         c++;
 
         if (*c == '$') {
-            dst->push_back(*(c++));
+            dst.push_back(*(c++));
             src_ptr = c;
             continue;
         } else if (*c == '\0') {
-            return true;
+            return dst;
         }
 
         std::string prop_name;
@@ -320,8 +313,7 @@
             const char* end = strchr(c, '}');
             if (!end) {
                 // failed to find closing brace, abort.
-                LOG(ERROR) << "unexpected end of string in '" << src << "', looking for }";
-                return false;
+                return Error() << "unexpected end of string in '" << src << "', looking for }";
             }
             prop_name = std::string(c, end);
             c = end + 1;
@@ -332,41 +324,45 @@
             }
         } else {
             prop_name = c;
-            LOG(ERROR) << "using deprecated syntax for specifying property '" << c << "', use ${name} instead";
+            if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
+                return Error() << "using deprecated syntax for specifying property '" << c
+                               << "', use ${name} instead";
+            } else {
+                LOG(ERROR) << "using deprecated syntax for specifying property '" << c
+                           << "', use ${name} instead";
+            }
             c += prop_name.size();
         }
 
         if (prop_name.empty()) {
-            LOG(ERROR) << "invalid zero-length property name in '" << src << "'";
-            return false;
+            return Error() << "invalid zero-length property name in '" << src << "'";
         }
 
         std::string prop_val = android::base::GetProperty(prop_name, "");
         if (prop_val.empty()) {
             if (def_val.empty()) {
-                LOG(ERROR) << "property '" << prop_name << "' doesn't exist while expanding '" << src << "'";
-                return false;
+                return Error() << "property '" << prop_name << "' doesn't exist while expanding '"
+                               << src << "'";
             }
             prop_val = def_val;
         }
 
-        dst->append(prop_val);
+        dst.append(prop_val);
         src_ptr = c;
     }
 
-    return true;
+    return dst;
 }
 
 static std::string init_android_dt_dir() {
     // Use the standard procfs-based path by default
     std::string android_dt_dir = kDefaultAndroidDtDir;
     // The platform may specify a custom Android DT path in kernel cmdline
-    import_kernel_cmdline(false,
-                          [&](const std::string& key, const std::string& value, bool in_qemu) {
-                              if (key == "androidboot.android_dt_dir") {
-                                  android_dt_dir = value;
-                              }
-                          });
+    ImportKernelCmdline([&](const std::string& key, const std::string& value) {
+        if (key == "androidboot.android_dt_dir") {
+            android_dt_dir = value;
+        }
+    });
     LOG(INFO) << "Using Android DT directory " << android_dt_dir;
     return android_dt_dir;
 }
@@ -426,6 +422,194 @@
     return true;
 }
 
+Result<void> IsLegalPropertyValue(const std::string& name, const std::string& value) {
+    if (value.size() >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
+        return Error() << "Property value too long";
+    }
+
+    if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
+        return Error() << "Value is not a UTF8 encoded string";
+    }
+
+    return {};
+}
+
+static FscryptAction FscryptInferAction(const std::string& dir) {
+    const std::string prefix = "/data/";
+
+    if (!android::base::StartsWith(dir, prefix)) {
+        return FscryptAction::kNone;
+    }
+
+    // Special-case /data/media/obb per b/64566063
+    if (dir == "/data/media/obb") {
+        // Try to set policy on this directory, but if it is non-empty this may fail.
+        return FscryptAction::kAttempt;
+    }
+
+    // Only set policy on first level /data directories
+    // To make this less restrictive, consider using a policy file.
+    // However this is overkill for as long as the policy is simply
+    // to apply a global policy to all /data folders created via makedir
+    if (dir.find_first_of('/', prefix.size()) != std::string::npos) {
+        return FscryptAction::kNone;
+    }
+
+    // Special case various directories that must not be encrypted,
+    // often because their subdirectories must be encrypted.
+    // This isn't a nice way to do this, see b/26641735
+    std::vector<std::string> directories_to_exclude = {
+            "lost+found", "system_ce", "system_de", "misc_ce",     "misc_de",
+            "vendor_ce",  "vendor_de", "media",     "data",        "user",
+            "user_de",    "apex",      "preloads",  "app-staging", "gsi",
+    };
+    for (const auto& d : directories_to_exclude) {
+        if ((prefix + d) == dir) {
+            return FscryptAction::kNone;
+        }
+    }
+    // Empty these directories if policy setting fails.
+    std::vector<std::string> wipe_on_failure = {
+            "rollback", "rollback-observer",  // b/139193659
+    };
+    for (const auto& d : wipe_on_failure) {
+        if ((prefix + d) == dir) {
+            return FscryptAction::kDeleteIfNecessary;
+        }
+    }
+    return FscryptAction::kRequire;
+}
+
+Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args) {
+    mode_t mode = 0755;
+    Result<uid_t> uid = -1;
+    Result<gid_t> gid = -1;
+    FscryptAction fscrypt_inferred_action = FscryptInferAction(args[1]);
+    FscryptAction fscrypt_action = fscrypt_inferred_action;
+    std::string ref_option = "ref";
+    bool set_option_encryption = false;
+    bool set_option_key = false;
+
+    for (size_t i = 2; i < args.size(); i++) {
+        switch (i) {
+            case 2:
+                mode = std::strtoul(args[2].c_str(), 0, 8);
+                break;
+            case 3:
+                uid = DecodeUid(args[3]);
+                if (!uid) {
+                    return Error()
+                           << "Unable to decode UID for '" << args[3] << "': " << uid.error();
+                }
+                break;
+            case 4:
+                gid = DecodeUid(args[4]);
+                if (!gid) {
+                    return Error()
+                           << "Unable to decode GID for '" << args[4] << "': " << gid.error();
+                }
+                break;
+            default:
+                auto parts = android::base::Split(args[i], "=");
+                if (parts.size() != 2) {
+                    return Error() << "Can't parse option: '" << args[i] << "'";
+                }
+                auto optname = parts[0];
+                auto optval = parts[1];
+                if (optname == "encryption") {
+                    if (set_option_encryption) {
+                        return Error() << "Duplicated option: '" << optname << "'";
+                    }
+                    if (optval == "Require") {
+                        fscrypt_action = FscryptAction::kRequire;
+                    } else if (optval == "None") {
+                        fscrypt_action = FscryptAction::kNone;
+                    } else if (optval == "Attempt") {
+                        fscrypt_action = FscryptAction::kAttempt;
+                    } else if (optval == "DeleteIfNecessary") {
+                        fscrypt_action = FscryptAction::kDeleteIfNecessary;
+                    } else {
+                        return Error() << "Unknown encryption option: '" << optval << "'";
+                    }
+                    set_option_encryption = true;
+                } else if (optname == "key") {
+                    if (set_option_key) {
+                        return Error() << "Duplicated option: '" << optname << "'";
+                    }
+                    if (optval == "ref" || optval == "per_boot_ref") {
+                        ref_option = optval;
+                    } else {
+                        return Error() << "Unknown key option: '" << optval << "'";
+                    }
+                    set_option_key = true;
+                } else {
+                    return Error() << "Unknown option: '" << args[i] << "'";
+                }
+        }
+    }
+    if (set_option_key && fscrypt_action == FscryptAction::kNone) {
+        return Error() << "Key option set but encryption action is none";
+    }
+    const std::string prefix = "/data/";
+    if (StartsWith(args[1], prefix) &&
+        args[1].find_first_of('/', prefix.size()) == std::string::npos) {
+        if (!set_option_encryption) {
+            LOG(WARNING) << "Top-level directory needs encryption action, eg mkdir " << args[1]
+                         << " <mode> <uid> <gid> encryption=Require";
+        }
+        if (fscrypt_action == FscryptAction::kNone) {
+            LOG(INFO) << "Not setting encryption policy on: " << args[1];
+        }
+    }
+    if (fscrypt_action != fscrypt_inferred_action) {
+        LOG(WARNING) << "Inferred action different from explicit one, expected "
+                     << static_cast<int>(fscrypt_inferred_action) << " but got "
+                     << static_cast<int>(fscrypt_action);
+    }
+
+    return MkdirOptions{args[1], mode, *uid, *gid, fscrypt_action, ref_option};
+}
+
+Result<std::pair<int, std::vector<std::string>>> ParseRestorecon(
+        const std::vector<std::string>& args) {
+    struct flag_type {
+        const char* name;
+        int value;
+    };
+    static const flag_type flags[] = {
+            {"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE},
+            {"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE},
+            {"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS},
+            {0, 0}};
+
+    int flag = 0;
+    std::vector<std::string> paths;
+
+    bool in_flags = true;
+    for (size_t i = 1; i < args.size(); ++i) {
+        if (android::base::StartsWith(args[i], "--")) {
+            if (!in_flags) {
+                return Error() << "flags must precede paths";
+            }
+            bool found = false;
+            for (size_t j = 0; flags[j].name; ++j) {
+                if (args[i] == flags[j].name) {
+                    flag |= flags[j].value;
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                return Error() << "bad flag " << args[i];
+            }
+        } else {
+            in_flags = false;
+            paths.emplace_back(args[i]);
+        }
+    }
+    return std::pair(flag, paths);
+}
+
 static void InitAborter(const char* abort_message) {
     // When init forks, it continues to use this aborter for LOG(FATAL), but we want children to
     // simply abort instead of trying to reboot the system.
@@ -434,7 +618,7 @@
         return;
     }
 
-    InitFatalReboot();
+    InitFatalReboot(SIGABRT);
 }
 
 // The kernel opens /dev/console and uses that fd for stdin/stdout/stderr if there is a serial
@@ -454,7 +638,7 @@
 // SetStdioToDevNull() must be called again in second stage init.
 void SetStdioToDevNull(char** argv) {
     // Make stdin/stdout/stderr all point to /dev/null.
-    int fd = open("/dev/null", O_RDWR);
+    int fd = open("/dev/null", O_RDWR);  // NOLINT(android-cloexec-open)
     if (fd == -1) {
         int saved_errno = errno;
         android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
diff --git a/init/util.h b/init/util.h
index 767620b..ad322d9 100644
--- a/init/util.h
+++ b/init/util.h
@@ -14,45 +14,43 @@
  * limitations under the License.
  */
 
-#ifndef _INIT_UTIL_H_
-#define _INIT_UTIL_H_
+#pragma once
 
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include <chrono>
 #include <functional>
-#include <ostream>
 #include <string>
 
 #include <android-base/chrono_utils.h>
-#include <selinux/label.h>
 
+#include "fscrypt_init_extensions.h"
 #include "result.h"
 
-#define COLDBOOT_DONE "/dev/.coldboot_done"
-
 using android::base::boot_clock;
-using namespace std::chrono_literals;
 
 namespace android {
 namespace init {
 
-int CreateSocket(const char* name, int type, bool passcred, mode_t perm, uid_t uid, gid_t gid,
-                 const char* socketcon);
+static const char kColdBootDoneProp[] = "ro.cold_boot_done";
+
+extern void (*trigger_shutdown)(const std::string& command);
+
+Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
+                         gid_t gid, const std::string& socketcon);
 
 Result<std::string> ReadFile(const std::string& path);
-Result<Success> WriteFile(const std::string& path, const std::string& content);
+Result<void> WriteFile(const std::string& path, const std::string& content);
 
 Result<uid_t> DecodeUid(const std::string& name);
 
 bool mkdir_recursive(const std::string& pathname, mode_t mode);
 int wait_for_file(const char *filename, std::chrono::nanoseconds timeout);
-void import_kernel_cmdline(bool in_qemu,
-                           const std::function<void(const std::string&, const std::string&, bool)>&);
+void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>&);
 bool make_dir(const std::string& path, mode_t mode);
 bool is_dir(const char* pathname);
-bool expand_props(const std::string& src, std::string* dst);
+Result<std::string> ExpandProps(const std::string& src);
 
 // Returns the platform's Android DT directory as specified in the kernel cmdline.
 // If the platform does not configure a custom DT path, returns the standard one (based in procfs).
@@ -62,11 +60,24 @@
 bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);
 
 bool IsLegalPropertyName(const std::string& name);
+Result<void> IsLegalPropertyValue(const std::string& name, const std::string& value);
+
+struct MkdirOptions {
+    std::string target;
+    mode_t mode;
+    uid_t uid;
+    gid_t gid;
+    FscryptAction fscrypt_action;
+    std::string ref_option;
+};
+
+Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args);
+
+Result<std::pair<int, std::vector<std::string>>> ParseRestorecon(
+        const std::vector<std::string>& args);
 
 void SetStdioToDevNull(char** argv);
 void InitKernelLogging(char** argv);
 bool IsRecoveryMode();
 }  // namespace init
 }  // namespace android
-
-#endif
diff --git a/init/util_test.cpp b/init/util_test.cpp
index 1b5afba..a8fcc87 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -34,7 +34,7 @@
     auto file_contents = ReadFile("/proc/does-not-exist");
     EXPECT_EQ(ENOENT, errno);
     ASSERT_FALSE(file_contents);
-    EXPECT_EQ("open() failed: No such file or directory", file_contents.error_string());
+    EXPECT_EQ("open() failed: No such file or directory", file_contents.error().message());
 }
 
 TEST(util, ReadFileGroupWriteable) {
@@ -45,7 +45,7 @@
     EXPECT_NE(-1, fchmodat(AT_FDCWD, tf.path, 0620, AT_SYMLINK_NOFOLLOW)) << strerror(errno);
     auto file_contents = ReadFile(tf.path);
     ASSERT_FALSE(file_contents) << strerror(errno);
-    EXPECT_EQ("Skipping insecure file", file_contents.error_string());
+    EXPECT_EQ("Skipping insecure file", file_contents.error().message());
 }
 
 TEST(util, ReadFileWorldWiteable) {
@@ -56,16 +56,17 @@
     EXPECT_NE(-1, fchmodat(AT_FDCWD, tf.path, 0602, AT_SYMLINK_NOFOLLOW)) << strerror(errno);
     auto file_contents = ReadFile(tf.path);
     ASSERT_FALSE(file_contents) << strerror(errno);
-    EXPECT_EQ("Skipping insecure file", file_contents.error_string());
+    EXPECT_EQ("Skipping insecure file", file_contents.error().message());
 }
 
 TEST(util, ReadFileSymbolicLink) {
     errno = 0;
-    // lrwxrwxrwx 1 root root 13 1970-01-01 00:00 charger -> /sbin/healthd
-    auto file_contents = ReadFile("/charger");
+    // lrw------- 1 root root 23 2008-12-31 19:00 default.prop -> system/etc/prop.default
+    auto file_contents = ReadFile("/default.prop");
     EXPECT_EQ(ELOOP, errno);
     ASSERT_FALSE(file_contents);
-    EXPECT_EQ("open() failed: Too many symbolic links encountered", file_contents.error_string());
+    EXPECT_EQ("open() failed: Too many symbolic links encountered",
+              file_contents.error().message());
 }
 
 TEST(util, ReadFileSuccess) {
@@ -130,7 +131,7 @@
 
     decoded_uid = DecodeUid("toot");
     EXPECT_FALSE(decoded_uid);
-    EXPECT_EQ("getpwnam failed: No such file or directory", decoded_uid.error_string());
+    EXPECT_EQ("getpwnam failed: No such file or directory", decoded_uid.error().message());
 
     decoded_uid = DecodeUid("123");
     EXPECT_TRUE(decoded_uid);
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 7f9a18a..565f2c3 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -42,6 +42,7 @@
     name: "libbacktrace_headers",
     vendor_available: true,
     recovery_available: true,
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
 }
 
@@ -96,7 +97,6 @@
             cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
         },
     },
-    whole_static_libs: ["libdemangle"],
 }
 
 cc_test_library {
@@ -134,7 +134,6 @@
     defaults: ["libbacktrace_common"],
     host_supported: true,
     srcs: [
-        "backtrace_offline_test.cpp",
         "backtrace_test.cpp",
     ],
 
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index 71980d7..3e050ab 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -28,13 +28,13 @@
 #include <backtrace/Backtrace.h>
 #include <backtrace/BacktraceMap.h>
 
-#include <demangle.h>
-
 #include "BacktraceLog.h"
 #include "UnwindStack.h"
 
 using android::base::StringPrintf;
 
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
+
 //-------------------------------------------------------------------------
 // Backtrace functions.
 //-------------------------------------------------------------------------
@@ -63,7 +63,14 @@
   if (map->start == 0 || (map->flags & PROT_DEVICE_MAP)) {
     return "";
   }
-  return demangle(GetFunctionNameRaw(pc, offset).c_str());
+  std::string name(GetFunctionNameRaw(pc, offset));
+  char* demangled_name = __cxa_demangle(name.c_str(), nullptr, nullptr, nullptr);
+  if (demangled_name != nullptr) {
+    name = demangled_name;
+    free(demangled_name);
+    return name;
+  }
+  return name;
 }
 
 bool Backtrace::VerifyReadWordArgs(uint64_t ptr, word_t* out_value) {
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 36640cd..624711f 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -24,7 +24,6 @@
 #include <string>
 
 #include <backtrace/Backtrace.h>
-#include <demangle.h>
 #include <unwindstack/Elf.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Maps.h>
@@ -41,6 +40,8 @@
 #include "UnwindStack.h"
 #include "UnwindStackMap.h"
 
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
+
 bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
                        std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
                        std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
@@ -115,7 +116,13 @@
     back_frame->pc = frame->pc;
     back_frame->sp = frame->sp;
 
-    back_frame->func_name = demangle(frame->function_name.c_str());
+    char* demangled_name = __cxa_demangle(frame->function_name.c_str(), nullptr, nullptr, nullptr);
+    if (demangled_name != nullptr) {
+      back_frame->func_name = demangled_name;
+      free(demangled_name);
+    } else {
+      back_frame->func_name = frame->function_name;
+    }
     back_frame->func_offset = frame->function_offset;
 
     back_frame->map.name = frame->map_name;
@@ -129,22 +136,6 @@
   return true;
 }
 
-bool Backtrace::UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
-                              const backtrace_stackinfo_t& stack,
-                              std::vector<backtrace_frame_data_t>* frames,
-                              BacktraceUnwindError* error) {
-  UnwindStackOfflineMap* offline_map = reinterpret_cast<UnwindStackOfflineMap*>(back_map);
-  // Create the process memory from the stack data since this will almost
-  // always be different each unwind.
-  if (!offline_map->CreateProcessMemory(stack)) {
-    if (error != nullptr) {
-      error->error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
-    }
-    return false;
-  }
-  return Backtrace::Unwind(regs, back_map, frames, 0U, nullptr, error);
-}
-
 UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
     : BacktraceCurrent(pid, tid, map) {}
 
@@ -171,7 +162,7 @@
 }
 
 UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
-    : BacktracePtrace(pid, tid, map), memory_(pid) {}
+    : BacktracePtrace(pid, tid, map), memory_(unwindstack::Memory::CreateProcessMemory(pid)) {}
 
 std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
   return GetMap()->GetFunctionName(pc, offset);
@@ -189,73 +180,5 @@
 }
 
 size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
-  return memory_.Read(addr, buffer, bytes);
-}
-
-UnwindStackOffline::UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map,
-                                       bool map_shared)
-    : Backtrace(pid, tid, map), arch_(arch) {
-  map_shared_ = map_shared;
-}
-
-bool UnwindStackOffline::Unwind(size_t num_ignore_frames, void* ucontext) {
-  if (ucontext == nullptr) {
-    return false;
-  }
-
-  unwindstack::ArchEnum arch;
-  switch (arch_) {
-    case ARCH_ARM:
-      arch = unwindstack::ARCH_ARM;
-      break;
-    case ARCH_ARM64:
-      arch = unwindstack::ARCH_ARM64;
-      break;
-    case ARCH_X86:
-      arch = unwindstack::ARCH_X86;
-      break;
-    case ARCH_X86_64:
-      arch = unwindstack::ARCH_X86_64;
-      break;
-    default:
-      return false;
-  }
-
-  std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
-
-  return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
-}
-
-std::string UnwindStackOffline::GetFunctionNameRaw(uint64_t, uint64_t*) {
-  return "";
-}
-
-size_t UnwindStackOffline::Read(uint64_t, uint8_t*, size_t) {
-  return 0;
-}
-
-bool UnwindStackOffline::ReadWord(uint64_t, word_t*) {
-  return false;
-}
-
-Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
-                                    const std::vector<backtrace_map_t>& maps,
-                                    const backtrace_stackinfo_t& stack) {
-  std::unique_ptr<UnwindStackOfflineMap> map(
-      reinterpret_cast<UnwindStackOfflineMap*>(BacktraceMap::CreateOffline(pid, maps)));
-  if (map.get() == nullptr || !map->CreateProcessMemory(stack)) {
-    return nullptr;
-  }
-  return new UnwindStackOffline(arch, pid, tid, map.release(), false);
-}
-
-Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
-  if (map == nullptr) {
-    return nullptr;
-  }
-  return new UnwindStackOffline(arch, pid, tid, map, true);
-}
-
-void Backtrace::SetGlobalElfCache(bool enable) {
-  unwindstack::Elf::SetCachingEnabled(enable);
+  return memory_->Read(addr, buffer, bytes);
 }
diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h
index 4ec591d..47f6757 100644
--- a/libbacktrace/UnwindStack.h
+++ b/libbacktrace/UnwindStack.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 
 #include <backtrace/BacktraceMap.h>
@@ -49,23 +50,7 @@
   size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
 
  private:
-  unwindstack::MemoryRemote memory_;
-};
-
-class UnwindStackOffline : public Backtrace {
- public:
-  UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map, bool map_shared);
-
-  bool Unwind(size_t num_ignore_frames, void* context) override;
-
-  std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override;
-
-  size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
-
-  bool ReadWord(uint64_t ptr, word_t* out_value) override;
-
- private:
-  ArchEnum arch_;
+  std::shared_ptr<unwindstack::Memory> memory_;
 };
 
 #endif  // _LIBBACKTRACE_UNWIND_STACK_H
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 4518891..aa0b17c 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -132,43 +132,6 @@
   return process_memory_;
 }
 
-UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {}
-
-bool UnwindStackOfflineMap::Build() {
-  return false;
-}
-
-bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps) {
-  for (const backtrace_map_t& map : backtrace_maps) {
-    maps_.push_back(map);
-  }
-
-  std::sort(maps_.begin(), maps_.end(),
-            [](const backtrace_map_t& a, const backtrace_map_t& b) { return a.start < b.start; });
-
-  unwindstack::Maps* maps = new unwindstack::Maps;
-  stack_maps_.reset(maps);
-  for (const backtrace_map_t& map : maps_) {
-    maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias);
-  }
-  return true;
-}
-
-bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& stack) {
-  if (stack.start >= stack.end) {
-    return false;
-  }
-
-  // Create the process memory from the stack data.
-  if (memory_ == nullptr) {
-    memory_ = new unwindstack::MemoryOfflineBuffer(stack.data, stack.start, stack.end);
-    process_memory_.reset(memory_);
-  } else {
-    memory_->Reset(stack.data, stack.start, stack.end);
-  }
-  return true;
-}
-
 //-------------------------------------------------------------------------
 // BacktraceMap create function.
 //-------------------------------------------------------------------------
@@ -189,15 +152,3 @@
   }
   return map;
 }
-
-//-------------------------------------------------------------------------
-// BacktraceMap create offline function.
-//-------------------------------------------------------------------------
-BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps) {
-  UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid);
-  if (!map->Build(maps)) {
-    delete map;
-    return nullptr;
-  }
-  return map;
-}
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index e19b605..f0e7d8b 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -33,6 +33,7 @@
 #include <unwindstack/Elf.h>
 #include <unwindstack/JitDebug.h>
 #include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
 
 // Forward declarations.
 class UnwindDexFile;
@@ -74,19 +75,4 @@
   unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN;
 };
 
-class UnwindStackOfflineMap : public UnwindStackMap {
- public:
-  UnwindStackOfflineMap(pid_t pid);
-  ~UnwindStackOfflineMap() = default;
-
-  bool Build() override;
-
-  bool Build(const std::vector<backtrace_map_t>& maps);
-
-  bool CreateProcessMemory(const backtrace_stackinfo_t& stack);
-
- private:
-  unwindstack::MemoryOfflineBuffer* memory_ = nullptr;
-};
-
 #endif  // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libbacktrace/backtrace_offline_test.cpp b/libbacktrace/backtrace_offline_test.cpp
deleted file mode 100644
index 662fb99..0000000
--- a/libbacktrace/backtrace_offline_test.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Copyright (C) 2015 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 <inttypes.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/threads.h>
-#include <backtrace/Backtrace.h>
-#include <backtrace/BacktraceMap.h>
-
-#include <gtest/gtest.h>
-
-#include "BacktraceTest.h"
-
-struct FunctionSymbol {
-  std::string name;
-  uint64_t start;
-  uint64_t end;
-};
-
-static std::vector<FunctionSymbol> GetFunctionSymbols() {
-  std::vector<FunctionSymbol> symbols = {
-      {"unknown_start", 0, 0},
-      {"test_level_one", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_one_), 0},
-      {"test_level_two", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_two_), 0},
-      {"test_level_three", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_three_), 0},
-      {"test_level_four", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_four_), 0},
-      {"test_recursive_call", reinterpret_cast<uint64_t>(&BacktraceTest::test_recursive_call_), 0},
-      {"test_get_context_and_wait",
-       reinterpret_cast<uint64_t>(&BacktraceTest::test_get_context_and_wait_), 0},
-      {"unknown_end", static_cast<uint64_t>(-1), static_cast<uint64_t>(-1)},
-  };
-  std::sort(
-      symbols.begin(), symbols.end(),
-      [](const FunctionSymbol& s1, const FunctionSymbol& s2) { return s1.start < s2.start; });
-  for (size_t i = 0; i + 1 < symbols.size(); ++i) {
-    symbols[i].end = symbols[i + 1].start;
-  }
-  return symbols;
-}
-
-static std::string RawDataToHexString(const void* data, size_t size) {
-  const uint8_t* p = static_cast<const uint8_t*>(data);
-  std::string s;
-  for (size_t i = 0; i < size; ++i) {
-    s += android::base::StringPrintf("%02x", p[i]);
-  }
-  return s;
-}
-
-static void HexStringToRawData(const char* s, std::vector<uint8_t>* data, size_t size) {
-  for (size_t i = 0; i < size; ++i) {
-    int value;
-    sscanf(s, "%02x", &value);
-    data->push_back(value);
-    s += 2;
-  }
-}
-
-struct OfflineThreadArg {
-  std::vector<uint8_t> ucontext;
-  pid_t tid;
-  volatile int exit_flag;
-};
-
-static void* OfflineThreadFunc(void* arg) {
-  OfflineThreadArg* fn_arg = reinterpret_cast<OfflineThreadArg*>(arg);
-  fn_arg->tid = android::base::GetThreadId();
-  BacktraceTest::test_get_context_and_wait_(&fn_arg->ucontext, &fn_arg->exit_flag);
-  return nullptr;
-}
-
-std::string GetTestPath(const std::string& arch, const std::string& path) {
-  return android::base::GetExecutableDirectory() + "/testdata/" + arch + '/' + path;
-}
-
-// This test is disable because it is for generating test data.
-TEST_F(BacktraceTest, DISABLED_generate_offline_testdata) {
-  // Create a thread to generate the needed stack and registers information.
-  const size_t stack_size = 16 * 1024;
-  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-  ASSERT_NE(MAP_FAILED, stack);
-  uint64_t stack_addr = reinterpret_cast<uint64_t>(stack);
-  pthread_attr_t attr;
-  ASSERT_EQ(0, pthread_attr_init(&attr));
-  ASSERT_EQ(0, pthread_attr_setstack(&attr, reinterpret_cast<void*>(stack), stack_size));
-  pthread_t thread;
-  OfflineThreadArg arg;
-  arg.exit_flag = 0;
-  ASSERT_EQ(0, pthread_create(&thread, &attr, OfflineThreadFunc, &arg));
-  // Wait for the offline thread to generate the stack and context information.
-  sleep(1);
-  // Copy the stack information.
-  std::vector<uint8_t> stack_data(reinterpret_cast<uint8_t*>(stack),
-                                  reinterpret_cast<uint8_t*>(stack) + stack_size);
-  arg.exit_flag = 1;
-  ASSERT_EQ(0, pthread_join(thread, nullptr));
-  ASSERT_EQ(0, munmap(stack, stack_size));
-
-  std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid()));
-  ASSERT_TRUE(map != nullptr);
-
-  backtrace_stackinfo_t stack_info;
-  stack_info.start = stack_addr;
-  stack_info.end = stack_addr + stack_size;
-  stack_info.data = stack_data.data();
-
-  // Generate offline testdata.
-  std::string testdata;
-  // 1. Dump pid, tid
-  testdata += android::base::StringPrintf("pid: %d tid: %d\n", getpid(), arg.tid);
-  // 2. Dump maps
-  for (auto it = map->begin(); it != map->end(); ++it) {
-    const backtrace_map_t* entry = *it;
-    testdata +=
-        android::base::StringPrintf("map: start: %" PRIx64 " end: %" PRIx64 " offset: %" PRIx64
-                                    " load_bias: %" PRIx64 " flags: %d name: %s\n",
-                                    entry->start, entry->end, entry->offset, entry->load_bias,
-                                    entry->flags, entry->name.c_str());
-  }
-  // 3. Dump ucontext
-  testdata += android::base::StringPrintf("ucontext: %zu ", arg.ucontext.size());
-  testdata += RawDataToHexString(arg.ucontext.data(), arg.ucontext.size());
-  testdata.push_back('\n');
-
-  // 4. Dump stack
-  testdata += android::base::StringPrintf(
-      "stack: start: %" PRIx64 " end: %" PRIx64 " size: %zu ",
-      stack_info.start, stack_info.end, stack_data.size());
-  testdata += RawDataToHexString(stack_data.data(), stack_data.size());
-  testdata.push_back('\n');
-
-  // 5. Dump function symbols
-  std::vector<FunctionSymbol> function_symbols = GetFunctionSymbols();
-  for (const auto& symbol : function_symbols) {
-    testdata +=
-        android::base::StringPrintf("function: start: %" PRIx64 " end: %" PRIx64 " name: %s\n",
-                                    symbol.start, symbol.end, symbol.name.c_str());
-  }
-
-  ASSERT_TRUE(android::base::WriteStringToFile(testdata, "offline_testdata"));
-}
-
-// Return the name of the function which matches the address. Although we don't know the
-// exact end of each function, it is accurate enough for the tests.
-static std::string FunctionNameForAddress(uint64_t addr,
-                                          const std::vector<FunctionSymbol>& symbols) {
-  for (auto& symbol : symbols) {
-    if (addr >= symbol.start && addr < symbol.end) {
-      return symbol.name;
-    }
-  }
-  return "";
-}
-
-struct OfflineTestData {
-  int pid;
-  int tid;
-  std::vector<backtrace_map_t> maps;
-  std::vector<uint8_t> ucontext;
-  backtrace_stackinfo_t stack_info;
-  std::vector<uint8_t> stack;
-  std::vector<FunctionSymbol> symbols;
-};
-
-bool ReadOfflineTestData(const std::string offline_testdata_path, OfflineTestData* testdata) {
-  std::string s;
-  if (!android::base::ReadFileToString(offline_testdata_path, &s)) {
-    return false;
-  }
-  // Parse offline_testdata.
-  std::vector<std::string> lines = android::base::Split(s, "\n");
-  for (const auto& line : lines) {
-    if (android::base::StartsWith(line, "pid:")) {
-      sscanf(line.c_str(), "pid: %d tid: %d", &testdata->pid, &testdata->tid);
-    } else if (android::base::StartsWith(line, "map:")) {
-      testdata->maps.resize(testdata->maps.size() + 1);
-      backtrace_map_t& map = testdata->maps.back();
-      int pos;
-      sscanf(line.c_str(),
-             "map: start: %" SCNx64 " end: %" SCNx64 " offset: %" SCNx64 " load_bias: %" SCNx64
-             " flags: %d name: %n",
-             &map.start, &map.end, &map.offset, &map.load_bias, &map.flags, &pos);
-      map.name = android::base::Trim(line.substr(pos));
-    } else if (android::base::StartsWith(line, "ucontext:")) {
-      size_t size;
-      int pos;
-      testdata->ucontext.clear();
-      sscanf(line.c_str(), "ucontext: %zu %n", &size, &pos);
-      HexStringToRawData(&line[pos], &testdata->ucontext, size);
-    } else if (android::base::StartsWith(line, "stack:")) {
-      size_t size;
-      int pos;
-      sscanf(line.c_str(),
-             "stack: start: %" SCNx64 " end: %" SCNx64 " size: %zu %n",
-             &testdata->stack_info.start, &testdata->stack_info.end, &size, &pos);
-      CHECK_EQ(testdata->stack_info.end - testdata->stack_info.start, size);
-      testdata->stack.clear();
-      HexStringToRawData(&line[pos], &testdata->stack, size);
-      testdata->stack_info.data = testdata->stack.data();
-    } else if (android::base::StartsWith(line, "function:")) {
-      testdata->symbols.resize(testdata->symbols.size() + 1);
-      FunctionSymbol& symbol = testdata->symbols.back();
-      int pos;
-      sscanf(line.c_str(), "function: start: %" SCNx64 " end: %" SCNx64 " name: %n", &symbol.start,
-             &symbol.end, &pos);
-      symbol.name = line.substr(pos);
-    }
-  }
-  return true;
-}
-
-static void BacktraceOfflineTest(std::string arch_str, const std::string& testlib_name) {
-  const std::string testlib_path(GetTestPath(arch_str, testlib_name));
-  const std::string offline_testdata_path(GetTestPath(arch_str, "offline_testdata"));
-  OfflineTestData testdata;
-  ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata)) << "Failed " << arch_str;
-
-  // Fix path of libbacktrace_testlib.so.
-  for (auto& map : testdata.maps) {
-    if (map.name.find("libbacktrace_test.so") != std::string::npos) {
-      map.name = testlib_path;
-    }
-  }
-
-  Backtrace::ArchEnum arch;
-  if (arch_str == "arm") {
-    arch = Backtrace::ARCH_ARM;
-  } else if (arch_str == "arm64") {
-    arch = Backtrace::ARCH_ARM64;
-  } else if (arch_str == "x86") {
-    arch = Backtrace::ARCH_X86;
-  } else if (arch_str == "x86_64") {
-    arch = Backtrace::ARCH_X86_64;
-  } else {
-    abort();
-  }
-
-  std::unique_ptr<Backtrace> backtrace(Backtrace::CreateOffline(
-      arch, testdata.pid, testdata.tid, testdata.maps, testdata.stack_info));
-  ASSERT_TRUE(backtrace != nullptr) << "Failed " << arch_str;
-
-  ASSERT_TRUE(backtrace->Unwind(0, testdata.ucontext.data())) << "Failed " << arch_str;
-
-  // Collect pc values of the call stack frames.
-  std::vector<uint64_t> pc_values;
-  for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
-    pc_values.push_back(backtrace->GetFrame(i)->pc);
-  }
-
-  size_t test_one_index = 0;
-  for (size_t i = 0; i < pc_values.size(); ++i) {
-    if (FunctionNameForAddress(pc_values[i], testdata.symbols) == "test_level_one") {
-      test_one_index = i;
-      break;
-    }
-  }
-
-  ASSERT_GE(test_one_index, 3u) << "Failed " << arch_str;
-  ASSERT_EQ("test_level_one", FunctionNameForAddress(pc_values[test_one_index], testdata.symbols))
-      << "Failed " << arch_str;
-  ASSERT_EQ("test_level_two", FunctionNameForAddress(pc_values[test_one_index - 1], testdata.symbols))
-      << "Failed " << arch_str;
-  ASSERT_EQ("test_level_three",
-            FunctionNameForAddress(pc_values[test_one_index - 2], testdata.symbols))
-      << "Failed " << arch_str;
-  ASSERT_EQ("test_level_four",
-            FunctionNameForAddress(pc_values[test_one_index - 3], testdata.symbols))
-      << "Failed " << arch_str;
-}
-
-// For now, these tests can only run on the given architectures.
-TEST_F(BacktraceTest, offline_eh_frame) {
-  BacktraceOfflineTest("arm64", "libbacktrace_test_eh_frame.so");
-  BacktraceOfflineTest("x86_64", "libbacktrace_test_eh_frame.so");
-}
-
-TEST_F(BacktraceTest, offline_debug_frame) {
-  BacktraceOfflineTest("arm", "libbacktrace_test_debug_frame.so");
-  BacktraceOfflineTest("x86", "libbacktrace_test_debug_frame.so");
-}
-
-TEST_F(BacktraceTest, offline_gnu_debugdata) {
-  BacktraceOfflineTest("arm", "libbacktrace_test_gnu_debugdata.so");
-  BacktraceOfflineTest("x86", "libbacktrace_test_gnu_debugdata.so");
-}
-
-TEST_F(BacktraceTest, offline_arm_exidx) {
-  BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so");
-}
-
-static void LibUnwindingTest(const std::string& arch_str, const std::string& testdata_name,
-                             const std::string& testlib_name) {
-  const std::string testlib_path(GetTestPath(arch_str, testlib_name));
-  struct stat st;
-  ASSERT_EQ(0, stat(testlib_path.c_str(), &st)) << "can't find testlib " << testlib_path;
-
-  const std::string offline_testdata_path(GetTestPath(arch_str, testdata_name));
-  OfflineTestData testdata;
-  ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata));
-
-  // Fix path of the testlib.
-  for (auto& map : testdata.maps) {
-    if (map.name.find(testlib_name) != std::string::npos) {
-      map.name = testlib_path;
-    }
-  }
-
-  Backtrace::ArchEnum arch;
-  if (arch_str == "arm") {
-    arch = Backtrace::ARCH_ARM;
-  } else if (arch_str == "arm64") {
-    arch = Backtrace::ARCH_ARM64;
-  } else if (arch_str == "x86") {
-    arch = Backtrace::ARCH_X86;
-  } else if (arch_str == "x86_64") {
-    arch = Backtrace::ARCH_X86_64;
-  } else {
-    ASSERT_TRUE(false) << "Unsupported arch " << arch_str;
-    abort();
-  }
-
-  // Do offline backtrace.
-  std::unique_ptr<Backtrace> backtrace(Backtrace::CreateOffline(
-      arch, testdata.pid, testdata.tid, testdata.maps, testdata.stack_info));
-  ASSERT_TRUE(backtrace != nullptr);
-
-  ASSERT_TRUE(backtrace->Unwind(0, testdata.ucontext.data()));
-
-  ASSERT_EQ(testdata.symbols.size(), backtrace->NumFrames());
-  for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
-    std::string name = FunctionNameForAddress(backtrace->GetFrame(i)->rel_pc, testdata.symbols);
-    ASSERT_EQ(name, testdata.symbols[i].name);
-  }
-  ASSERT_TRUE(backtrace->GetError().error_code == BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED ||
-              backtrace->GetError().error_code == BACKTRACE_UNWIND_ERROR_MAP_MISSING ||
-              backtrace->GetError().error_code == BACKTRACE_UNWIND_ERROR_REPEATED_FRAME);
-}
-
-// This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx
-// overlap with each other, which appears in /system/lib/libart.so.
-TEST_F(BacktraceTest, offline_unwind_mix_eh_frame_and_arm_exidx) {
-  LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so");
-}
-
-TEST_F(BacktraceTest, offline_debug_frame_with_load_bias) {
-  LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so");
-}
-
-TEST_F(BacktraceTest, offline_try_armexidx_after_debug_frame) {
-  LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so");
-}
-
-TEST_F(BacktraceTest, offline_cie_with_P_augmentation) {
-  // Make sure we can unwind through functions with CIE entry containing P augmentation, which
-  // makes unwinding library reading personality handler from memory. One example is
-  // /system/lib64/libskia.so.
-  LibUnwindingTest("arm64", "offline_testdata_for_libskia", "libskia.so");
-}
-
-TEST_F(BacktraceTest, offline_empty_eh_frame_hdr) {
-  // Make sure we can unwind through libraries with empty .eh_frame_hdr section. One example is
-  // /vendor/lib64/egl/eglSubDriverAndroid.so.
-  LibUnwindingTest("arm64", "offline_testdata_for_eglSubDriverAndroid", "eglSubDriverAndroid.so");
-}
-
-TEST_F(BacktraceTest, offline_max_frames_limit) {
-  // The length of callchain can reach 256 when recording an application.
-  ASSERT_GE(MAX_BACKTRACE_FRAMES, 256);
-}
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index 404e7e8..664b531 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -126,24 +126,6 @@
   // If map is not NULL, the map is still owned by the caller.
   static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = nullptr);
 
-  // Create an offline Backtrace object that can be used to do an unwind without a process
-  // that is still running. By default, information is only cached in the map
-  // file. If the calling code creates the map, data can be cached between
-  // unwinds. If not, all cached data will be destroyed when the Backtrace
-  // object is destroyed.
-  static Backtrace* CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
-                                  const std::vector<backtrace_map_t>& maps,
-                                  const backtrace_stackinfo_t& stack);
-  static Backtrace* CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map);
-
-  // Create an offline Backtrace object that can be used to do an unwind without a process
-  // that is still running. If cache_file is set to true, then elf information will be cached
-  // for this call. The cached information survives until the calling process ends. This means
-  // that subsequent calls to create offline Backtrace objects will continue to use the same
-  // cache. It also assumes that the elf files used for each offline unwind are the same.
-  static Backtrace* CreateOffline(pid_t pid, pid_t tid, BacktraceMap* map,
-                                  const backtrace_stackinfo_t& stack, bool cache_file = false);
-
   virtual ~Backtrace();
 
   // Get the current stack trace and store in the backtrace_ structure.
@@ -153,11 +135,6 @@
                      std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
                      std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr);
 
-  static bool UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
-                            const backtrace_stackinfo_t& stack_info,
-                            std::vector<backtrace_frame_data_t>* frames,
-                            BacktraceUnwindError* error = nullptr);
-
   // Get the function name and offset into the function given the pc.
   // If the string is empty, then no valid function name was found,
   // or the pc is not in any valid map.
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index c564271..e000a00 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -69,8 +69,6 @@
   // is unsupported.
   static BacktraceMap* Create(pid_t pid, bool uncached = false);
 
-  static BacktraceMap* CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps);
-
   virtual ~BacktraceMap();
 
   class iterator : public std::iterator<std::bidirectional_iterator_tag, backtrace_map_t*> {
@@ -81,7 +79,7 @@
       index_++;
       return *this;
     }
-    iterator& operator++(int increment) {
+    const iterator operator++(int increment) {
       index_ += increment;
       return *this;
     }
@@ -89,7 +87,7 @@
       index_--;
       return *this;
     }
-    iterator& operator--(int decrement) {
+    const iterator operator--(int decrement) {
       index_ -= decrement;
       return *this;
     }
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 619bc56..334364e 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -34,6 +34,7 @@
     vendor_available: true,
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
     target: {
         vendor: {
@@ -57,6 +58,7 @@
     },
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
     srcs: [
         "config_utils.cpp",
         "canned_fs_config.cpp",
@@ -65,8 +67,6 @@
         "native_handle.cpp",
         "record_stream.cpp",
         "sockets.cpp",
-        "strdup16to8.cpp",
-        "strdup8to16.cpp",
         "strlcpy.c",
         "threads.cpp",
     ],
@@ -197,7 +197,10 @@
 
 cc_defaults {
     name: "libcutils_test_default",
-    srcs: ["sockets_test.cpp"],
+    srcs: [
+        "native_handle_test.cpp",
+        "sockets_test.cpp",
+    ],
 
     target: {
         android: {
@@ -244,6 +247,7 @@
     defaults: ["libcutils_test_default"],
     host_supported: true,
     shared_libs: test_libraries,
+    require_root: true,
 }
 
 cc_test {
@@ -255,6 +259,7 @@
         "libcgrouprc_format",
     ] + test_libraries,
     stl: "libc++_static",
+    require_root: true,
 
     target: {
         android: {
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index e67b458..340572c 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -23,9 +23,6 @@
  */
 #define LOG_TAG "ashmem"
 
-#ifndef __ANDROID_VNDK__
-#include <dlfcn.h>
-#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/ashmem.h>
@@ -42,11 +39,11 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 
-#define ASHMEM_DEVICE "/dev/ashmem"
-
 /* Will be added to UAPI once upstream change is merged */
 #define F_SEAL_FUTURE_WRITE 0x0010
 
@@ -66,32 +63,6 @@
 static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /*
- * We use ashmemd to enforce that apps don't open /dev/ashmem directly. Vendor
- * code can't access system aidl services per Treble requirements. So we limit
- * ashmemd access to the system variant of libcutils.
- */
-#ifndef __ANDROID_VNDK__
-using openFdType = int (*)();
-
-static openFdType openFd;
-
-openFdType initOpenAshmemFd() {
-    openFdType openFd = nullptr;
-    void* handle = dlopen("libashmemd_client.so", RTLD_NOW);
-    if (!handle) {
-        ALOGE("Failed to dlopen() libashmemd_client.so: %s", dlerror());
-        return openFd;
-    }
-
-    openFd = reinterpret_cast<openFdType>(dlsym(handle, "openAshmemdFd"));
-    if (!openFd) {
-        ALOGE("Failed to dlsym() openAshmemdFd() function: %s", dlerror());
-    }
-    return openFd;
-}
-#endif
-
-/*
  * has_memfd_support() determines if the device can use memfd. memfd support
  * has been there for long time, but certain things in it may be missing.  We
  * check for needed support in it. Also we check if the VNDK version of
@@ -215,25 +186,31 @@
     return memfd_supported;
 }
 
+static std::string get_ashmem_device_path() {
+    static const std::string boot_id_path = "/proc/sys/kernel/random/boot_id";
+    std::string boot_id;
+    if (!android::base::ReadFileToString(boot_id_path, &boot_id)) {
+        ALOGE("Failed to read %s: %s.\n", boot_id_path.c_str(), strerror(errno));
+        return "";
+    };
+    boot_id = android::base::Trim(boot_id);
+
+    return "/dev/ashmem" + boot_id;
+}
+
 /* logistics of getting file descriptor for ashmem */
 static int __ashmem_open_locked()
 {
+    static const std::string ashmem_device_path = get_ashmem_device_path();
+
     int ret;
     struct stat st;
 
-    int fd = -1;
-#ifndef __ANDROID_VNDK__
-    if (!openFd) {
-        openFd = initOpenAshmemFd();
+    if (ashmem_device_path.empty()) {
+        return -1;
     }
 
-    if (openFd) {
-        fd = openFd();
-    }
-#endif
-    if (fd < 0) {
-        fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
-    }
+    int fd = TEMP_FAILURE_RETRY(open(ashmem_device_path.c_str(), O_RDWR | O_CLOEXEC));
     if (fd < 0) {
         return fd;
     }
@@ -485,11 +462,3 @@
 
     return __ashmem_check_failure(fd, TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)));
 }
-
-void ashmem_init() {
-#ifndef __ANDROID_VNDK__
-    pthread_mutex_lock(&__ashmem_lock);
-    openFd = initOpenAshmemFd();
-    pthread_mutex_unlock(&__ashmem_lock);
-#endif  //__ANDROID_VNDK__
-}
diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp
index 32446d4..2ba1eb0 100644
--- a/libcutils/ashmem-host.cpp
+++ b/libcutils/ashmem-host.cpp
@@ -34,6 +34,29 @@
 
 #include <utils/Compat.h>
 
+static bool ashmem_validate_stat(int fd, struct stat* buf) {
+    int result = fstat(fd, buf);
+    if (result == -1) {
+        return false;
+    }
+
+    /*
+     * Check if this is an "ashmem" region.
+     * TODO: This is very hacky, and can easily break.
+     * We need some reliable indicator.
+     */
+    if (!(buf->st_nlink == 0 && S_ISREG(buf->st_mode))) {
+        errno = ENOTTY;
+        return false;
+    }
+    return true;
+}
+
+int ashmem_valid(int fd) {
+    struct stat buf;
+    return ashmem_validate_stat(fd, &buf);
+}
+
 int ashmem_create_region(const char* /*ignored*/, size_t size) {
     char pattern[PATH_MAX];
     snprintf(pattern, sizeof(pattern), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid());
@@ -65,22 +88,9 @@
 int ashmem_get_size_region(int fd)
 {
     struct stat buf;
-    int result = fstat(fd, &buf);
-    if (result == -1) {
-        return -1;
-    }
-
-    /*
-     * Check if this is an "ashmem" region.
-     * TODO: This is very hacky, and can easily break.
-     * We need some reliable indicator.
-     */
-    if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) {
-        errno = ENOTTY;
+    if (!ashmem_validate_stat(fd, &buf)) {
         return -1;
     }
 
     return buf.st_size;
 }
-
-void ashmem_init() {}
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index a5f4f0e..dc31b28 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -39,6 +39,8 @@
 #include <private/android_filesystem_config.h>
 #include <utils/Compat.h>
 
+#include "fs_config.h"
+
 #ifndef O_BINARY
 #define O_BINARY 0
 #endif
@@ -46,20 +48,8 @@
 using android::base::EndsWith;
 using android::base::StartsWith;
 
-// My kingdom for <endian.h>
-static inline uint16_t get2LE(const uint8_t* src) {
-    return src[0] | (src[1] << 8);
-}
-
-static inline uint64_t get8LE(const uint8_t* src) {
-    uint32_t low, high;
-
-    low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-    high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-    return ((uint64_t)high << 32) | (uint64_t)low;
-}
-
 #define ALIGN(x, alignment) (((x) + ((alignment)-1)) & ~((alignment)-1))
+#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
 
 // Rules for directories.
 // These rules are applied based on "first match", so they
@@ -88,14 +78,15 @@
     { 00771, AID_SYSTEM,       AID_SYSTEM,       0, "data" },
     { 00755, AID_ROOT,         AID_SYSTEM,       0, "mnt" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "product/bin" },
-    { 00750, AID_ROOT,         AID_SHELL,        0, "sbin" },
     { 00777, AID_ROOT,         AID_ROOT,         0, "sdcard" },
     { 00751, AID_ROOT,         AID_SDCARD_R,     0, "storage" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "system/bin" },
     { 00755, AID_ROOT,         AID_ROOT,         0, "system/etc/ppp" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "system/vendor" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "system/xbin" },
-    { 00755, AID_ROOT,         AID_SHELL,        0, "system/apex/*/bin" },
+    { 00751, AID_ROOT,         AID_SHELL,        0, "system/apex/*/bin" },
+    { 00751, AID_ROOT,         AID_SHELL,        0, "system_ext/bin" },
+    { 00751, AID_ROOT,         AID_SHELL,        0, "system_ext/apex/*/bin" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/bin" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "vendor" },
     { 00755, AID_ROOT,         AID_ROOT,         0, 0 },
@@ -117,7 +108,7 @@
 // oem/ file-system since the intent is to provide support for customized
 // portions of a separate vendor.img or oem.img.  Has to remain open so that
 // customization can also land on /system/vendor, /system/oem, /system/odm,
-// /system/product or /system/product_services.
+// /system/product or /system/system_ext.
 //
 // We expect build-time checking or filtering when constructing the associated
 // fs_config_* files (see build/tools/fs_config/fs_config_generate.c)
@@ -129,15 +120,12 @@
 static const char odm_conf_file[] = "/odm/etc/fs_config_files";
 static const char product_conf_dir[] = "/product/etc/fs_config_dirs";
 static const char product_conf_file[] = "/product/etc/fs_config_files";
-static const char product_services_conf_dir[] = "/product_services/etc/fs_config_dirs";
-static const char product_services_conf_file[] = "/product_services/etc/fs_config_files";
+static const char system_ext_conf_dir[] = "/system_ext/etc/fs_config_dirs";
+static const char system_ext_conf_file[] = "/system_ext/etc/fs_config_files";
 static const char* conf[][2] = {
-        {sys_conf_file, sys_conf_dir},
-        {ven_conf_file, ven_conf_dir},
-        {oem_conf_file, oem_conf_dir},
-        {odm_conf_file, odm_conf_dir},
-        {product_conf_file, product_conf_dir},
-        {product_services_conf_file, product_services_conf_dir},
+        {sys_conf_file, sys_conf_dir},         {ven_conf_file, ven_conf_dir},
+        {oem_conf_file, oem_conf_dir},         {odm_conf_file, odm_conf_dir},
+        {product_conf_file, product_conf_dir}, {system_ext_conf_file, system_ext_conf_dir},
 };
 
 // Do not use android_files to grant Linux capabilities.  Use ambient capabilities in their
@@ -169,14 +157,12 @@
     { 00600, AID_ROOT,      AID_ROOT,      0, "product/build.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, product_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, product_conf_file + 1 },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "product_services/build.prop" },
-    { 00444, AID_ROOT,      AID_ROOT,      0, product_services_conf_dir + 1 },
-    { 00444, AID_ROOT,      AID_ROOT,      0, product_services_conf_file + 1 },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system_ext/build.prop" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, system_ext_conf_dir + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, system_ext_conf_file + 1 },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump32" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump64" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/debuggerd" },
-    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
     { 00550, AID_LOGD,      AID_LOGD,      0, "system/bin/logd" },
     { 00700, AID_ROOT,      AID_ROOT,      0, "system/bin/secilc" },
     { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
@@ -188,9 +174,10 @@
     { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
-    { 00440, AID_ROOT,      AID_ROOT,      0, "system/etc/recovery.img" },
+    { 00750, AID_ROOT,      AID_ROOT,      0, "vendor/bin/install-recovery.sh" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/build.prop" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/default.prop" },
+    { 00440, AID_ROOT,      AID_ROOT,      0, "vendor/etc/recovery.img" },
     { 00444, AID_ROOT,      AID_ROOT,      0, ven_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, ven_conf_file + 1 },
 
@@ -217,11 +204,13 @@
     { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
     { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "odm/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "product/bin/*" },
-    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/apex/*/bin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system_ext/bin/*" },
+    { 00755, AID_ROOT,      AID_SHELL,     0, "system_ext/apex/*/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
     { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
@@ -260,9 +249,9 @@
 }
 
 // if path is "odm/<stuff>", "oem/<stuff>", "product/<stuff>",
-// "product_services/<stuff>" or "vendor/<stuff>"
+// "system_ext/<stuff>" or "vendor/<stuff>"
 static bool is_partition(const std::string& path) {
-    static const char* partitions[] = {"odm/", "oem/", "product/", "product_services/", "vendor/"};
+    static const char* partitions[] = {"odm/", "oem/", "product/", "system_ext/", "vendor/"};
     for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) {
         if (StartsWith(path, partitions[i])) return true;
     }
@@ -296,20 +285,19 @@
     const int fnm_flags = FNM_NOESCAPE;
     if (fnmatch(pattern.c_str(), input.c_str(), fnm_flags) == 0) return true;
 
-    static constexpr const char* kSystem = "system/";
-    if (StartsWith(input, kSystem)) {
-        input.erase(0, strlen(kSystem));
-    } else if (input.size() <= strlen(kSystem)) {
-        return false;
-    } else if (StartsWith(pattern, kSystem)) {
-        pattern.erase(0, strlen(kSystem));
-    } else {
-        return false;
+    // Check match between logical partition's files and patterns.
+    static constexpr const char* kLogicalPartitions[] = {"system/product/", "system/system_ext/",
+                                                         "system/vendor/", "vendor/odm/"};
+    for (auto& logical_partition : kLogicalPartitions) {
+        if (StartsWith(input, logical_partition)) {
+            std::string input_in_partition = input.substr(input.find('/') + 1);
+            if (!is_partition(input_in_partition)) continue;
+            if (fnmatch(pattern.c_str(), input_in_partition.c_str(), fnm_flags) == 0) {
+                return true;
+            }
+        }
     }
-
-    if (!is_partition(pattern)) return false;
-    if (!is_partition(input)) return false;
-    return fnmatch(pattern.c_str(), input.c_str(), fnm_flags) == 0;
+    return false;
 }
 #ifndef __ANDROID_VNDK__
 auto __for_testing_only__fs_config_cmp = fs_config_cmp;
@@ -334,7 +322,7 @@
 
         while (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) == sizeof(header)) {
             char* prefix;
-            uint16_t host_len = get2LE((const uint8_t*)&header.len);
+            uint16_t host_len = header.len;
             ssize_t len, remainder = host_len - sizeof(header);
             if (remainder <= 0) {
                 ALOGE("%s len is corrupted", conf[which][dir]);
@@ -359,10 +347,10 @@
             if (fs_config_cmp(dir, prefix, len, path, plen)) {
                 free(prefix);
                 close(fd);
-                *uid = get2LE((const uint8_t*)&(header.uid));
-                *gid = get2LE((const uint8_t*)&(header.gid));
-                *mode = (*mode & (~07777)) | get2LE((const uint8_t*)&(header.mode));
-                *capabilities = get8LE((const uint8_t*)&(header.capabilities));
+                *uid = header.uid;
+                *gid = header.gid;
+                *mode = (*mode & (~07777)) | header.mode;
+                *capabilities = header.capabilities;
                 return;
             }
             free(prefix);
@@ -380,21 +368,3 @@
     *mode = (*mode & (~07777)) | pc->mode;
     *capabilities = pc->capabilities;
 }
-
-ssize_t fs_config_generate(char* buffer, size_t length, const struct fs_path_config* pc) {
-    struct fs_path_config_from_file* p = (struct fs_path_config_from_file*)buffer;
-    size_t len = ALIGN(sizeof(*p) + strlen(pc->prefix) + 1, sizeof(uint64_t));
-
-    if ((length < len) || (len > UINT16_MAX)) {
-        return -ENOSPC;
-    }
-    memset(p, 0, len);
-    uint16_t host_len = len;
-    p->len = get2LE((const uint8_t*)&host_len);
-    p->mode = get2LE((const uint8_t*)&(pc->mode));
-    p->uid = get2LE((const uint8_t*)&(pc->uid));
-    p->gid = get2LE((const uint8_t*)&(pc->gid));
-    p->capabilities = get8LE((const uint8_t*)&(pc->capabilities));
-    strcpy(p->prefix, pc->prefix);
-    return len;
-}
diff --git a/libcutils/fs_config.h b/libcutils/fs_config.h
new file mode 100644
index 0000000..66ad48b
--- /dev/null
+++ b/libcutils/fs_config.h
@@ -0,0 +1,37 @@
+/*
+ * 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 <stdint.h>
+
+// Binary format for the runtime <partition>/etc/fs_config_(dirs|files) filesystem override files.
+struct fs_path_config_from_file {
+    uint16_t len;
+    uint16_t mode;
+    uint16_t uid;
+    uint16_t gid;
+    uint64_t capabilities;
+    char prefix[];
+} __attribute__((__aligned__(sizeof(uint64_t))));
+
+struct fs_path_config {
+    unsigned mode;
+    unsigned uid;
+    unsigned gid;
+    uint64_t capabilities;
+    const char* prefix;
+};
diff --git a/libcutils/fs_config_test.cpp b/libcutils/fs_config_test.cpp
index c26315f..c6684b4 100644
--- a/libcutils/fs_config_test.cpp
+++ b/libcutils/fs_config_test.cpp
@@ -25,7 +25,8 @@
 #include <android-base/strings.h>
 
 #include <private/android_filesystem_config.h>
-#include <private/fs_config.h>
+
+#include "fs_config.h"
 
 extern const fs_path_config* __for_testing_only__android_dirs;
 extern const fs_path_config* __for_testing_only__android_files;
@@ -45,7 +46,7 @@
         // clang-format off
     { true,  "system/lib",             "system/lib/hw",           true  },
     { true,  "vendor/lib",             "system/vendor/lib/hw",    true  },
-    { true,  "system/vendor/lib",      "vendor/lib/hw",           true  },
+    { true,  "system/vendor/lib",      "vendor/lib/hw",           false },
     { true,  "system/vendor/lib",      "system/vendor/lib/hw",    true  },
     { true,  "foo/*/bar/*",            "foo/1/bar/2",             true  },
     { true,  "foo/*/bar/*",            "foo/1/bar",               true  },
@@ -55,13 +56,14 @@
     { false, "vendor/bin/wifi",        "system/vendor/bin/wifi",  true  },
     { false, "vendor/bin/wifi",        "system/vendor/bin/wifi2", false },
     { false, "system/vendor/bin/wifi", "system/vendor/bin/wifi",  true, },
-    { false, "odm/bin/wifi",           "system/odm/bin/wifi",     true  },
-    { false, "oem/bin/wifi",           "system/oem/bin/wifi",     true  },
+    { false, "odm/bin/wifi",           "system/odm/bin/wifi",     false },
+    { false, "odm/bin/wifi",           "vendor/odm/bin/wifi",     true  },
+    { false, "oem/bin/wifi",           "system/oem/bin/wifi",     false },
     { false, "data/bin/wifi",          "system/data/bin/wifi",    false },
     { false, "system/bin/*",           "system/bin/wifi",         true  },
     { false, "vendor/bin/*",           "system/vendor/bin/wifi",  true  },
     { false, "system/bin/*",           "system/bin",              false },
-    { false, "system/vendor/bin/*",    "vendor/bin/wifi",         true  },
+    { false, "system/vendor/bin/*",    "vendor/bin/wifi",         false },
     { false, "foo/*/bar/*",            "foo/1/bar/2",             true  },
     { false, "foo/*/bar/*",            "foo/1/bar",               false },
     { false, "foo/*/bar/*",            "foo/1/bar/2/3",           true  },
diff --git a/libcutils/include/cutils/ashmem.h b/libcutils/include/cutils/ashmem.h
index abc5068..d80caa6 100644
--- a/libcutils/include/cutils/ashmem.h
+++ b/libcutils/include/cutils/ashmem.h
@@ -26,7 +26,6 @@
 int ashmem_pin_region(int fd, size_t offset, size_t len);
 int ashmem_unpin_region(int fd, size_t offset, size_t len);
 int ashmem_get_size_region(int fd);
-void ashmem_init();
 
 #ifdef __cplusplus
 }
diff --git a/libcutils/include/cutils/jstring.h b/libcutils/include/cutils/jstring.h
deleted file mode 100644
index a342608..0000000
--- a/libcutils/include/cutils/jstring.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2006 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 __CUTILS_STRING16_H
-#define __CUTILS_STRING16_H
-
-#include <stdint.h>
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if __STDC_VERSION__ < 201112L && __cplusplus < 201103L
-  typedef uint16_t char16_t;
-#endif
-  // otherwise char16_t is a keyword with the right semantics
-
-extern char * strndup16to8 (const char16_t* s, size_t n);
-extern size_t strnlen16to8 (const char16_t* s, size_t n);
-extern char * strncpy16to8 (char *dest, const char16_t*s, size_t n);
-
-extern char16_t * strdup8to16 (const char* s, size_t *out_len);
-extern size_t strlen8to16 (const char* utf8Str);
-extern char16_t * strcpy8to16 (char16_t *dest, const char*s, size_t *out_len);
-extern char16_t * strcpylen8to16 (char16_t *dest, const char*s, int length,
-    size_t *out_len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CUTILS_STRING16_H */
diff --git a/libcutils/include/cutils/sockets.h b/libcutils/include/cutils/sockets.h
index 285f150..be21a8f 100644
--- a/libcutils/include/cutils/sockets.h
+++ b/libcutils/include/cutils/sockets.h
@@ -103,14 +103,6 @@
 int socket_close(cutils_socket_t sock);
 
 /*
- * Sets socket receive timeout using SO_RCVTIMEO. Setting |timeout_ms| to 0
- * disables receive timeouts.
- *
- * Return 0 on success.
- */
-int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms);
-
-/*
  * Returns the local port the socket is bound to or -1 on error.
  */
 int socket_get_local_port(cutils_socket_t sock);
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 63c3793..e1e8230 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -28,17 +28,10 @@
  *   mediadrm
  * Whose friendly names do not match the #define statements.
  *
- * Additionally, AID_OEM_RESERVED_START and AID_OEM_RESERVED_END
- * can be used to define reserved OEM ranges used for sanity checks
- * during the build process. The rules are, they must end with START/END
- * The proper convention is incrementing a number like so:
- * AID_OEM_RESERVED_START
- * AID_OEM_RESERVED_1_START
- * AID_OEM_RESERVED_2_START
- * ...
- * The same applies to the END.
- * They are not required to be in order, but must not overlap each other and
- * must define a START and END'ing range. START must be smaller than END.
+ * This file must only be used for platform (Google managed, and submitted through AOSP), AIDs.  3rd
+ * party AIDs must be added via config.fs, which will place them in the corresponding partition's
+ * passwd and group files.  There are ranges in this file reserved for AIDs for each 3rd party
+ * partition, from which the system reads passwd and group files.
  */
 
 #ifndef _ANDROID_FILESYSTEM_CONFIG_H_
@@ -135,14 +128,19 @@
 #define AID_GPU_SERVICE 1072     /* GPU service daemon */
 #define AID_NETWORK_STACK 1073   /* network stack service */
 #define AID_GSID 1074            /* GSI service daemon */
+#define AID_FSVERITY_CERT 1075   /* fs-verity key ownership in keystore */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
 #define AID_CACHE 2001 /* cache access */
 #define AID_DIAG 2002  /* access to diagnostic resources */
 
-/* The range 2900-2999 is reserved for OEM, and must never be
- * used here */
+/* The range 2900-2999 is reserved for the vendor partition */
+/* Note that the two 'OEM' ranges pre-dated the vendor partition, so they take the legacy 'OEM'
+ * name. Additionally, they pre-dated passwd/group files, so there are users and groups named oem_#
+ * created automatically for all values in these ranges.  If there is a user/group in a passwd/group
+ * file corresponding to this range, both the oem_# and user/group names will resolve to the same
+ * value. */
 #define AID_OEM_RESERVED_START 2900
 #define AID_OEM_RESERVED_END 2999
 
@@ -159,10 +157,26 @@
 #define AID_WAKELOCK 3010     /* Allow system wakelock read/write access */
 #define AID_UHID 3011         /* Allow read/write to /dev/uhid node */
 
-/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
+/* The range 5000-5999 is also reserved for vendor partition. */
 #define AID_OEM_RESERVED_2_START 5000
 #define AID_OEM_RESERVED_2_END 5999
 
+/* The range 6000-6499 is reserved for the system partition. */
+#define AID_SYSTEM_RESERVED_START 6000
+#define AID_SYSTEM_RESERVED_END 6499
+
+/* The range 6500-6999 is reserved for the odm partition. */
+#define AID_ODM_RESERVED_START 6500
+#define AID_ODM_RESERVED_END 6999
+
+/* The range 7000-7499 is reserved for the product partition. */
+#define AID_PRODUCT_RESERVED_START 7000
+#define AID_PRODUCT_RESERVED_END 7499
+
+/* The range 7500-7999 is reserved for the system_ext partition. */
+#define AID_SYSTEM_EXT_RESERVED_START 7500
+#define AID_SYSTEM_EXT_RESERVED_END 7999
+
 #define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
 #define AID_MISC 9998      /* access to misc storage */
 #define AID_NOBODY 9999
diff --git a/libcutils/include/private/fs_config.h b/libcutils/include/private/fs_config.h
index 8926491..8a9a1ff 100644
--- a/libcutils/include/private/fs_config.h
+++ b/libcutils/include/private/fs_config.h
@@ -19,44 +19,17 @@
 ** by the device side of adb.
 */
 
-#ifndef _LIBS_CUTILS_PRIVATE_FS_CONFIG_H
-#define _LIBS_CUTILS_PRIVATE_FS_CONFIG_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/cdefs.h>
-#include <sys/types.h>
 
 #if defined(__BIONIC__)
 #include <linux/capability.h>
 #else  // defined(__BIONIC__)
-#include "android_filesystem_capability.h"
+#include <private/android_filesystem_capability.h>
 #endif  // defined(__BIONIC__)
 
-#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
-
-/*
- * binary format for the runtime <partition>/etc/fs_config_(dirs|files)
- * filesystem override files.
- */
-
-/* The following structure is stored little endian */
-struct fs_path_config_from_file {
-    uint16_t len;
-    uint16_t mode;
-    uint16_t uid;
-    uint16_t gid;
-    uint64_t capabilities;
-    char prefix[];
-} __attribute__((__aligned__(sizeof(uint64_t))));
-
-struct fs_path_config {
-    unsigned mode;
-    unsigned uid;
-    unsigned gid;
-    uint64_t capabilities;
-    const char* prefix;
-};
-
 /* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
 
 __BEGIN_DECLS
@@ -74,8 +47,4 @@
 void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
                unsigned* mode, uint64_t* capabilities);
 
-ssize_t fs_config_generate(char* buffer, size_t length, const struct fs_path_config* pc);
-
 __END_DECLS
-
-#endif /* _LIBS_CUTILS_PRIVATE_FS_CONFIG_H */
diff --git a/libcutils/include_vndk/cutils/jstring.h b/libcutils/include_vndk/cutils/jstring.h
deleted file mode 120000
index f3fd546..0000000
--- a/libcutils/include_vndk/cutils/jstring.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/jstring.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/log.h b/libcutils/include_vndk/cutils/log.h
deleted file mode 100644
index 21dc11e..0000000
--- a/libcutils/include_vndk/cutils/log.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*Special log.h file for VNDK linking modules*/
-/*
- * Copyright (C) 2005-2017 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 _LIBS_CUTIL_LOG_H
-#define _LIBS_CUTIL_LOG_H
-
-/* We do not know if developer wanted log/log.h or subset android/log.h */
-#include <log/log.h>
-
-#if defined(__GNUC__)
-#if defined( __clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-W#warnings"
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wpedantic"
-#elif (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR > 9))
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-W#warnings"
-#else
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wcpp"
-#endif
-#endif
-
-#warning "Deprecated: don't include cutils/log.h, use either android/log.h or log/log.h"
-
-#if defined(__GNUC__)
-#if defined( __clang__)
-#pragma clang diagnostic pop
-#endif
-#pragma GCC diagnostic pop
-#endif
-
-#endif /* _LIBS_CUTIL_LOG_H */
diff --git a/libcutils/include_vndk/cutils/log.h b/libcutils/include_vndk/cutils/log.h
new file mode 120000
index 0000000..b868d50
--- /dev/null
+++ b/libcutils/include_vndk/cutils/log.h
@@ -0,0 +1 @@
+../../include/cutils/log.h
\ No newline at end of file
diff --git a/libcutils/native_handle.cpp b/libcutils/native_handle.cpp
index b409e5b..5804ab1 100644
--- a/libcutils/native_handle.cpp
+++ b/libcutils/native_handle.cpp
@@ -81,6 +81,8 @@
 }
 
 int native_handle_close(const native_handle_t* h) {
+    if (!h) return 0;
+
     if (h->version != sizeof(native_handle_t)) return -EINVAL;
 
     int saved_errno = errno;
diff --git a/libnativeloader/test/api_test.c b/libcutils/native_handle_test.cpp
similarity index 70%
copy from libnativeloader/test/api_test.c
copy to libcutils/native_handle_test.cpp
index e7025fd..c1e2f0b 100644
--- a/libnativeloader/test/api_test.c
+++ b/libcutils/native_handle_test.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-/* The main purpose of this test is to ensure this C header compiles in C, so
- * that no C++ features inadvertently leak into the C ABI. */
-#include "nativeloader/native_loader.h"
+#include <cutils/native_handle.h>
 
-int main(int argc, char** argv) {
-  (void)argc;
-  (void)argv;
-  return 0;
+#include <gtest/gtest.h>
+
+TEST(native_handle, native_handle_delete) {
+    ASSERT_EQ(0, native_handle_delete(nullptr));
+}
+
+TEST(native_handle, native_handle_close) {
+    ASSERT_EQ(0, native_handle_close(nullptr));
 }
diff --git a/libcutils/sched_policy_test.cpp b/libcutils/sched_policy_test.cpp
index a321c90..b9e2832 100644
--- a/libcutils/sched_policy_test.cpp
+++ b/libcutils/sched_policy_test.cpp
@@ -107,6 +107,18 @@
 
 TEST(SchedPolicy, get_sched_policy_name) {
     EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
-    EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
-    EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
+    EXPECT_EQ(nullptr, get_sched_policy_name(SchedPolicy(-2)));
+    EXPECT_EQ(nullptr, get_sched_policy_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_cpuset_policy_profile_name) {
+    EXPECT_STREQ("CPUSET_SP_BACKGROUND", get_cpuset_policy_profile_name(SP_BACKGROUND));
+    EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SchedPolicy(-2)));
+    EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_sched_policy_profile_name) {
+    EXPECT_STREQ("SCHED_SP_BACKGROUND", get_sched_policy_profile_name(SP_BACKGROUND));
+    EXPECT_EQ(nullptr, get_sched_policy_profile_name(SchedPolicy(-2)));
+    EXPECT_EQ(nullptr, get_sched_policy_profile_name(SP_CNT));
 }
diff --git a/libcutils/sockets_test.cpp b/libcutils/sockets_test.cpp
index b762ac1..1fa40bc 100644
--- a/libcutils/sockets_test.cpp
+++ b/libcutils/sockets_test.cpp
@@ -73,25 +73,6 @@
     EXPECT_EQ(0, socket_close(client));
 }
 
-// Tests receive timeout. The timing verification logic must be very coarse to
-// make sure different systems can all pass these tests.
-void TestReceiveTimeout(cutils_socket_t sock) {
-    time_t start_time;
-    char buffer[32];
-
-    // Make sure a 20ms timeout completes in 1 second or less.
-    EXPECT_EQ(0, socket_set_receive_timeout(sock, 20));
-    start_time = time(nullptr);
-    EXPECT_EQ(-1, recv(sock, buffer, sizeof(buffer), 0));
-    EXPECT_LE(difftime(time(nullptr), start_time), 1.0);
-
-    // Make sure a 1250ms timeout takes 1 second or more.
-    EXPECT_EQ(0, socket_set_receive_timeout(sock, 1250));
-    start_time = time(nullptr);
-    EXPECT_EQ(-1, recv(sock, buffer, sizeof(buffer), 0));
-    EXPECT_LE(1.0, difftime(time(nullptr), start_time));
-}
-
 // Tests socket_get_local_port().
 TEST(SocketsTest, TestGetLocalPort) {
     cutils_socket_t server;
@@ -157,32 +138,6 @@
     TestConnectedSockets(handler, client, SOCK_STREAM);
 }
 
-// Tests setting a receive timeout for UDP sockets.
-TEST(SocketsTest, TestUdpReceiveTimeout) {
-    cutils_socket_t sock = socket_inaddr_any_server(0, SOCK_DGRAM);
-    ASSERT_NE(INVALID_SOCKET, sock);
-
-    TestReceiveTimeout(sock);
-
-    EXPECT_EQ(0, socket_close(sock));
-}
-
-// Tests setting a receive timeout for TCP sockets.
-TEST(SocketsTest, TestTcpReceiveTimeout) {
-    cutils_socket_t server = socket_inaddr_any_server(0, SOCK_STREAM);
-    ASSERT_NE(INVALID_SOCKET, server);
-
-    cutils_socket_t client = socket_network_client(
-            "localhost", socket_get_local_port(server), SOCK_STREAM);
-    cutils_socket_t handler = accept(server, nullptr, nullptr);
-    EXPECT_EQ(0, socket_close(server));
-
-    TestReceiveTimeout(handler);
-
-    EXPECT_EQ(0, socket_close(client));
-    EXPECT_EQ(0, socket_close(handler));
-}
-
 // Tests socket_send_buffers() failure.
 TEST(SocketsTest, TestSocketSendBuffersFailure) {
     EXPECT_EQ(-1, socket_send_buffers(INVALID_SOCKET, nullptr, 0));
diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp
index 6acdcd8..84663e6 100644
--- a/libcutils/sockets_unix.cpp
+++ b/libcutils/sockets_unix.cpp
@@ -31,13 +31,6 @@
     return close(sock);
 }
 
-int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) {
-    timeval tv;
-    tv.tv_sec = timeout_ms / 1000;
-    tv.tv_usec = (timeout_ms % 1000) * 1000;
-    return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
-}
-
 ssize_t socket_send_buffers(cutils_socket_t sock,
                             const cutils_socket_buffer_t* buffers,
                             size_t num_buffers) {
diff --git a/libcutils/sockets_windows.cpp b/libcutils/sockets_windows.cpp
index df14712..4adb796 100644
--- a/libcutils/sockets_windows.cpp
+++ b/libcutils/sockets_windows.cpp
@@ -54,11 +54,6 @@
     return closesocket(sock);
 }
 
-int socket_set_receive_timeout(cutils_socket_t sock, int timeout_ms) {
-    return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
-                      reinterpret_cast<char*>(&timeout_ms), sizeof(timeout_ms));
-}
-
 ssize_t socket_send_buffers(cutils_socket_t sock,
                             const cutils_socket_buffer_t* buffers,
                             size_t num_buffers) {
diff --git a/libcutils/strdup16to8.cpp b/libcutils/strdup16to8.cpp
deleted file mode 100644
index d89181e..0000000
--- a/libcutils/strdup16to8.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/* libs/cutils/strdup16to8.c
-**
-** Copyright 2006, 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 <cutils/jstring.h>
-
-#include <assert.h>
-#include <limits.h>  /* for SIZE_MAX */
-#include <stdlib.h>
-
-
-/**
- * Given a UTF-16 string, compute the length of the corresponding UTF-8
- * string in bytes.
- */
-extern size_t strnlen16to8(const char16_t* utf16Str, size_t len)
-{
-    size_t utf8Len = 0;
-
-    /* A small note on integer overflow. The result can
-     * potentially be as big as 3*len, which will overflow
-     * for len > SIZE_MAX/3.
-     *
-     * Moreover, the result of a strnlen16to8 is typically used
-     * to allocate a destination buffer to strncpy16to8 which
-     * requires one more byte to terminate the UTF-8 copy, and
-     * this is generally done by careless users by incrementing
-     * the result without checking for integer overflows, e.g.:
-     *
-     *   dst = malloc(strnlen16to8(utf16,len)+1)
-     *
-     * Due to this, the following code will try to detect
-     * overflows, and never return more than (SIZE_MAX-1)
-     * when it detects one. A careless user will try to malloc
-     * SIZE_MAX bytes, which will return NULL which can at least
-     * be detected appropriately.
-     *
-     * As far as I know, this function is only used by strndup16(),
-     * but better be safe than sorry.
-     */
-
-    /* Fast path for the usual case where 3*len is < SIZE_MAX-1.
-     */
-    if (len < (SIZE_MAX-1)/3) {
-        while (len != 0) {
-            len--;
-            unsigned int uic = *utf16Str++;
-
-            if (uic > 0x07ff)
-                utf8Len += 3;
-            else if (uic > 0x7f || uic == 0)
-                utf8Len += 2;
-            else
-                utf8Len++;
-        }
-        return utf8Len;
-    }
-
-    /* The slower but paranoid version */
-    while (len != 0) {
-        len--;
-        unsigned int  uic     = *utf16Str++;
-        size_t        utf8Cur = utf8Len;
-
-        if (uic > 0x07ff)
-            utf8Len += 3;
-        else if (uic > 0x7f || uic == 0)
-            utf8Len += 2;
-        else
-            utf8Len++;
-
-        if (utf8Len < utf8Cur) /* overflow detected */
-            return SIZE_MAX-1;
-    }
-
-    /* don't return SIZE_MAX to avoid common user bug */
-    if (utf8Len == SIZE_MAX)
-        utf8Len = SIZE_MAX-1;
-
-    return utf8Len;
-}
-
-
-/**
- * Convert a Java-Style UTF-16 string + length to a JNI-Style UTF-8 string.
- *
- * This basically means: embedded \0's in the UTF-16 string are encoded
- * as "0xc0 0x80"
- *
- * Make sure you allocate "utf8Str" with the result of strlen16to8() + 1,
- * not just "len".
- *
- * Please note, a terminated \0 is always added, so your result will always
- * be "strlen16to8() + 1" bytes long.
- */
-extern char* strncpy16to8(char* utf8Str, const char16_t* utf16Str, size_t len)
-{
-    char* utf8cur = utf8Str;
-
-    /* Note on overflows: We assume the user did check the result of
-     * strnlen16to8() properly or at a minimum checked the result of
-     * its malloc(SIZE_MAX) in case of overflow.
-     */
-    while (len != 0) {
-        len--;
-        unsigned int uic = *utf16Str++;
-
-        if (uic > 0x07ff) {
-            *utf8cur++ = (uic >> 12) | 0xe0;
-            *utf8cur++ = ((uic >> 6) & 0x3f) | 0x80;
-            *utf8cur++ = (uic & 0x3f) | 0x80;
-        } else if (uic > 0x7f || uic == 0) {
-            *utf8cur++ = (uic >> 6) | 0xc0;
-            *utf8cur++ = (uic & 0x3f) | 0x80;
-        } else {
-            *utf8cur++ = uic;
-
-            if (uic == 0) {
-                break;
-            }
-        }
-    }
-
-   *utf8cur = '\0';
-
-   return utf8Str;
-}
-
-/**
- * Convert a UTF-16 string to UTF-8.
- *
- */
-char * strndup16to8 (const char16_t* s, size_t n)
-{
-    if (s == NULL) {
-        return NULL;
-    }
-
-    size_t len = strnlen16to8(s, n);
-
-    /* We are paranoid, and we check for SIZE_MAX-1
-     * too since it is an overflow value for our
-     * strnlen16to8 implementation.
-     */
-    if (len >= SIZE_MAX-1)
-        return NULL;
-
-    char* ret = static_cast<char*>(malloc(len + 1));
-    if (ret == NULL)
-        return NULL;
-
-    strncpy16to8 (ret, s, n);
-
-    return ret;
-}
diff --git a/libcutils/strdup8to16.cpp b/libcutils/strdup8to16.cpp
deleted file mode 100644
index d1e51b9..0000000
--- a/libcutils/strdup8to16.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/* libs/cutils/strdup8to16.c
-**
-** Copyright 2006, 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 <cutils/jstring.h>
-
-#include <assert.h>
-#include <limits.h>
-#include <stdlib.h>
-
-/* See http://www.unicode.org/reports/tr22/ for discussion
- * on invalid sequences
- */
-
-#define UTF16_REPLACEMENT_CHAR 0xfffd
-
-/* Clever trick from Dianne that returns 1-4 depending on leading bit sequence*/
-#define UTF8_SEQ_LENGTH(ch) (((0xe5000000 >> (((ch) >> 3) & 0x1e)) & 3) + 1)
-
-/* note: macro expands to multiple lines */
-#define UTF8_SHIFT_AND_MASK(unicode, byte)  \
-            (unicode)<<=6; (unicode) |= (0x3f & (byte));
-
-#define UNICODE_UPPER_LIMIT 0x10fffd    
-
-/**
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strdup8to16 (const char* s, size_t *out_len)
-{
-    char16_t *ret;
-    size_t len;
-
-    if (s == NULL) return NULL;
-
-    len = strlen8to16(s);
-
-    // fail on overflow
-    if (len && SIZE_MAX/len < sizeof(char16_t))
-        return NULL;
-
-    // no plus-one here. UTF-16 strings are not null terminated
-    ret = (char16_t *) malloc (sizeof(char16_t) * len);
-
-    return strcpy8to16 (ret, s, out_len);
-}
-
-/**
- * Like "strlen", but for strings encoded with Java's modified UTF-8.
- *
- * The value returned is the number of UTF-16 characters required
- * to represent this string.
- */
-extern size_t strlen8to16 (const char* utf8Str)
-{
-    size_t len = 0;
-    int ic;
-    int expected = 0;
-
-    while ((ic = *utf8Str++) != '\0') {
-        /* bytes that start 0? or 11 are lead bytes and count as characters.*/
-        /* bytes that start 10 are extention bytes and are not counted */
-         
-        if ((ic & 0xc0) == 0x80) {
-            /* count the 0x80 extention bytes. if we have more than
-             * expected, then start counting them because strcpy8to16
-             * will insert UTF16_REPLACEMENT_CHAR's
-             */
-            expected--;
-            if (expected < 0) {
-                len++;
-            }
-        } else {
-            len++;
-            expected = UTF8_SEQ_LENGTH(ic) - 1;
-
-            /* this will result in a surrogate pair */
-            if (expected == 3) {
-                len++;
-            }
-        }
-    }
-
-    return len;
-}
-
-
-
-/*
- * Retrieve the next UTF-32 character from a UTF-8 string.
- *
- * Stops at inner \0's
- *
- * Returns UTF16_REPLACEMENT_CHAR if an invalid sequence is encountered
- *
- * Advances "*pUtf8Ptr" to the start of the next character.
- */
-static inline uint32_t getUtf32FromUtf8(const char** pUtf8Ptr)
-{
-    uint32_t ret;
-    int seq_len;
-    int i;
-
-    /* Mask for leader byte for lengths 1, 2, 3, and 4 respectively*/
-    static const unsigned char leaderMask[4] = {0xff, 0x1f, 0x0f, 0x07};
-
-    /* Bytes that start with bits "10" are not leading characters. */
-    if (((**pUtf8Ptr) & 0xc0) == 0x80) {
-        (*pUtf8Ptr)++;
-        return UTF16_REPLACEMENT_CHAR;
-    }
-
-    /* note we tolerate invalid leader 11111xxx here */    
-    seq_len = UTF8_SEQ_LENGTH(**pUtf8Ptr);
-
-    ret = (**pUtf8Ptr) & leaderMask [seq_len - 1];
-
-    if (**pUtf8Ptr == '\0') return ret;
-
-    (*pUtf8Ptr)++;
-    for (i = 1; i < seq_len ; i++, (*pUtf8Ptr)++) {
-        if ((**pUtf8Ptr) == '\0') return UTF16_REPLACEMENT_CHAR;
-        if (((**pUtf8Ptr) & 0xc0) != 0x80) return UTF16_REPLACEMENT_CHAR;
-
-        UTF8_SHIFT_AND_MASK(ret, **pUtf8Ptr);
-    }
-
-    return ret;
-}
-
-
-/**
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strcpy8to16 (char16_t *utf16Str, const char*utf8Str, 
-                                       size_t *out_len)
-{   
-    char16_t *dest = utf16Str;
-
-    while (*utf8Str != '\0') {
-        uint32_t ret;
-
-        ret = getUtf32FromUtf8(&utf8Str);
-
-        if (ret <= 0xffff) {
-            *dest++ = (char16_t) ret;
-        } else if (ret <= UNICODE_UPPER_LIMIT)  {
-            /* Create surrogate pairs */
-            /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
-
-            *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
-            *dest++ = 0xdc00 | ((ret - 0x10000) &  0x3ff);
-        } else {
-            *dest++ = UTF16_REPLACEMENT_CHAR;
-        }
-    }
-
-    *out_len = dest - utf16Str;
-
-    return utf16Str;
-}
-
-/**
- * length is the number of characters in the UTF-8 string.
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strcpylen8to16 (char16_t *utf16Str, const char*utf8Str,
-                                       int length, size_t *out_len)
-{
-    /* TODO: Share more of this code with the method above. Only 2 lines changed. */
-    
-    char16_t *dest = utf16Str;
-
-    const char *end = utf8Str + length; /* This line */
-    while (utf8Str < end) {             /* and this line changed. */
-        uint32_t ret;
-
-        ret = getUtf32FromUtf8(&utf8Str);
-
-        if (ret <= 0xffff) {
-            *dest++ = (char16_t) ret;
-        } else if (ret <= UNICODE_UPPER_LIMIT)  {
-            /* Create surrogate pairs */
-            /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
-
-            *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
-            *dest++ = 0xdc00 | ((ret - 0x10000) &  0x3ff);
-        } else {
-            *dest++ = UTF16_REPLACEMENT_CHAR;
-        }
-    }
-
-    *out_len = dest - utf16Str;
-
-    return utf16Str;
-}
diff --git a/libcutils/trace-dev.cpp b/libcutils/trace-dev.cpp
index 4da8215..bff16c1 100644
--- a/libcutils/trace-dev.cpp
+++ b/libcutils/trace-dev.cpp
@@ -34,12 +34,9 @@
     if (atrace_marker_fd == -1) {
         ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
         atrace_enabled_tags = 0;
-        goto done;
+    } else {
+      atrace_enabled_tags = atrace_get_property();
     }
-
-    atrace_enabled_tags = atrace_get_property();
-
-done:
     atomic_store_explicit(&atrace_is_ready, true, memory_order_release);
 }
 
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index 721de7c..bf244d2 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -60,7 +60,7 @@
     struct ucred* cred;
 
     *uid = -1;
-    ssize_t n = recvmsg(socket, &hdr, 0);
+    ssize_t n = TEMP_FAILURE_RETRY(recvmsg(socket, &hdr, 0));
     if (n <= 0) {
         return n;
     }
diff --git a/libgrallocusage/Android.bp b/libgrallocusage/Android.bp
index d27feb9..ce0c3c8 100644
--- a/libgrallocusage/Android.bp
+++ b/libgrallocusage/Android.bp
@@ -20,12 +20,7 @@
         "-Werror",
     ],
     cppflags: [
-        "-Weverything",
-        "-Wno-c++98-compat-pedantic",
-        // Hide errors in headers we include
-        "-Wno-global-constructors",
-        "-Wno-exit-time-destructors",
-        "-Wno-padded",
+        "-Wextra",
     ],
     srcs: ["GrallocUsageConversion.cpp"],
     export_include_dirs: ["include"],
diff --git a/libion/Android.bp b/libion/Android.bp
deleted file mode 100644
index 2f73d92..0000000
--- a/libion/Android.bp
+++ /dev/null
@@ -1,29 +0,0 @@
-cc_library {
-    name: "libion",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-        support_system_process: true,
-    },
-    srcs: ["ion.c"],
-    shared_libs: ["liblog"],
-    local_include_dirs: [
-        "include",
-        "kernel-headers",
-    ],
-    export_include_dirs: [
-        "include",
-        "kernel-headers",
-    ],
-    cflags: ["-Werror"],
-}
-
-cc_binary {
-    name: "iontest",
-    srcs: ["ion_test.c"],
-    static_libs: ["libion"],
-    shared_libs: ["liblog"],
-    cflags: ["-Werror"],
-}
-
-subdirs = ["tests"]
diff --git a/libion/include/ion/ion.h b/libion/include/ion/ion.h
deleted file mode 100644
index a60d24e..0000000
--- a/libion/include/ion/ion.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  ion.c
- *
- * Memory Allocator functions for ion
- *
- *   Copyright 2011 Google, Inc
- *
- *  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 __SYS_CORE_ION_H
-#define __SYS_CORE_ION_H
-
-#include <sys/types.h>
-#include <linux/ion.h>
-
-__BEGIN_DECLS
-
-struct ion_handle;
-
-int ion_open();
-int ion_close(int fd);
-int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
-              unsigned int flags, ion_user_handle_t *handle);
-int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask,
-              unsigned int flags, int *handle_fd);
-int ion_sync_fd(int fd, int handle_fd);
-int ion_free(int fd, ion_user_handle_t handle);
-int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
-            int flags, off_t offset, unsigned char **ptr, int *map_fd);
-int ion_share(int fd, ion_user_handle_t handle, int *share_fd);
-int ion_import(int fd, int share_fd, ion_user_handle_t *handle);
-
-/**
-  * Add 4.12+ kernel ION interfaces here for forward compatibility
-  * This should be needed till the pre-4.12+ ION interfaces are backported.
-  */
-int ion_query_heap_cnt(int fd, int* cnt);
-int ion_query_get_heaps(int fd, int cnt, void* buffers);
-
-int ion_is_legacy(int fd);
-
-__END_DECLS
-
-#endif /* __SYS_CORE_ION_H */
diff --git a/libion/ion.c b/libion/ion.c
deleted file mode 100644
index b8de5a4..0000000
--- a/libion/ion.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- *  ion.c
- *
- * Memory Allocator functions for ion
- *
- *   Copyright 2011 Google, Inc
- *
- *  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 "ion"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/ion.h>
-#include <stdatomic.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <ion/ion.h>
-#include "ion_4.12.h"
-
-#include <log/log.h>
-
-enum ion_version { ION_VERSION_UNKNOWN, ION_VERSION_MODERN, ION_VERSION_LEGACY };
-
-static atomic_int g_ion_version = ATOMIC_VAR_INIT(ION_VERSION_UNKNOWN);
-
-int ion_is_legacy(int fd) {
-    int version = atomic_load_explicit(&g_ion_version, memory_order_acquire);
-    if (version == ION_VERSION_UNKNOWN) {
-        /**
-          * Check for FREE IOCTL here; it is available only in the old
-          * kernels, not the new ones.
-          */
-        int err = ion_free(fd, (ion_user_handle_t)NULL);
-        version = (err == -ENOTTY) ? ION_VERSION_MODERN : ION_VERSION_LEGACY;
-        atomic_store_explicit(&g_ion_version, version, memory_order_release);
-    }
-    return version == ION_VERSION_LEGACY;
-}
-
-int ion_open() {
-    int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC);
-    if (fd < 0) ALOGE("open /dev/ion failed: %s", strerror(errno));
-
-    return fd;
-}
-
-int ion_close(int fd) {
-    int ret = close(fd);
-    if (ret < 0) return -errno;
-    return ret;
-}
-
-static int ion_ioctl(int fd, int req, void* arg) {
-    int ret = ioctl(fd, req, arg);
-    if (ret < 0) {
-        ALOGE("ioctl %x failed with code %d: %s", req, ret, strerror(errno));
-        return -errno;
-    }
-    return ret;
-}
-
-int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, unsigned int flags,
-              ion_user_handle_t* handle) {
-    int ret = 0;
-
-    if ((handle == NULL) || (!ion_is_legacy(fd))) return -EINVAL;
-
-    struct ion_allocation_data data = {
-        .len = len, .align = align, .heap_id_mask = heap_mask, .flags = flags,
-    };
-
-    ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
-    if (ret < 0) return ret;
-
-    *handle = data.handle;
-
-    return ret;
-}
-
-int ion_free(int fd, ion_user_handle_t handle) {
-    struct ion_handle_data data = {
-        .handle = handle,
-    };
-    return ion_ioctl(fd, ION_IOC_FREE, &data);
-}
-
-int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, int flags, off_t offset,
-            unsigned char** ptr, int* map_fd) {
-    if (!ion_is_legacy(fd)) return -EINVAL;
-    int ret;
-    unsigned char* tmp_ptr;
-    struct ion_fd_data data = {
-        .handle = handle,
-    };
-
-    if (map_fd == NULL) return -EINVAL;
-    if (ptr == NULL) return -EINVAL;
-
-    ret = ion_ioctl(fd, ION_IOC_MAP, &data);
-    if (ret < 0) return ret;
-    if (data.fd < 0) {
-        ALOGE("map ioctl returned negative fd");
-        return -EINVAL;
-    }
-    tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset);
-    if (tmp_ptr == MAP_FAILED) {
-        ALOGE("mmap failed: %s", strerror(errno));
-        return -errno;
-    }
-    *map_fd = data.fd;
-    *ptr = tmp_ptr;
-    return ret;
-}
-
-int ion_share(int fd, ion_user_handle_t handle, int* share_fd) {
-    int ret;
-    struct ion_fd_data data = {
-        .handle = handle,
-    };
-
-    if (!ion_is_legacy(fd)) return -EINVAL;
-    if (share_fd == NULL) return -EINVAL;
-
-    ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
-    if (ret < 0) return ret;
-    if (data.fd < 0) {
-        ALOGE("share ioctl returned negative fd");
-        return -EINVAL;
-    }
-    *share_fd = data.fd;
-    return ret;
-}
-
-int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask, unsigned int flags,
-                 int* handle_fd) {
-    ion_user_handle_t handle;
-    int ret;
-
-    if (!ion_is_legacy(fd)) {
-        struct ion_new_allocation_data data = {
-            .len = len,
-            .heap_id_mask = heap_mask,
-            .flags = flags,
-        };
-
-        ret = ion_ioctl(fd, ION_IOC_NEW_ALLOC, &data);
-        if (ret < 0) return ret;
-        *handle_fd = data.fd;
-    } else {
-        ret = ion_alloc(fd, len, align, heap_mask, flags, &handle);
-        if (ret < 0) return ret;
-        ret = ion_share(fd, handle, handle_fd);
-        ion_free(fd, handle);
-    }
-    return ret;
-}
-
-int ion_import(int fd, int share_fd, ion_user_handle_t* handle) {
-    int ret;
-    struct ion_fd_data data = {
-        .fd = share_fd,
-    };
-
-    if (!ion_is_legacy(fd)) return -EINVAL;
-
-    if (handle == NULL) return -EINVAL;
-
-    ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
-    if (ret < 0) return ret;
-    *handle = data.handle;
-    return ret;
-}
-
-int ion_sync_fd(int fd, int handle_fd) {
-    struct ion_fd_data data = {
-        .fd = handle_fd,
-    };
-
-    if (!ion_is_legacy(fd)) return -EINVAL;
-
-    return ion_ioctl(fd, ION_IOC_SYNC, &data);
-}
-
-int ion_query_heap_cnt(int fd, int* cnt) {
-    int ret;
-    struct ion_heap_query query;
-
-    memset(&query, 0, sizeof(query));
-
-    ret = ion_ioctl(fd, ION_IOC_HEAP_QUERY, &query);
-    if (ret < 0) return ret;
-
-    *cnt = query.cnt;
-    return ret;
-}
-
-int ion_query_get_heaps(int fd, int cnt, void* buffers) {
-    int ret;
-    struct ion_heap_query query = {
-        .cnt = cnt, .heaps = (uintptr_t)buffers,
-    };
-
-    ret = ion_ioctl(fd, ION_IOC_HEAP_QUERY, &query);
-    return ret;
-}
diff --git a/libion/ion_4.12.h b/libion/ion_4.12.h
deleted file mode 100644
index 6ae79d4..0000000
--- a/libion/ion_4.12.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Adapted from drivers/staging/android/uapi/ion.h
- *
- * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _UAPI_LINUX_ION_NEW_H
-#define _UAPI_LINUX_ION_NEW_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
-
-/**
- * DOC: Ion Userspace API
- *
- * create a client by opening /dev/ion
- * most operations handled via following ioctls
- *
- */
-
-/**
- * struct ion_new_allocation_data - metadata passed from userspace for allocations
- * @len:		size of the allocation
- * @heap_id_mask:	mask of heap ids to allocate from
- * @flags:		flags passed to heap
- * @handle:		pointer that will be populated with a cookie to use to
- *			refer to this allocation
- *
- * Provided by userspace as an argument to the ioctl - added _new to denote
- * this belongs to the new ION interface.
- */
-struct ion_new_allocation_data {
-    __u64 len;
-    __u32 heap_id_mask;
-    __u32 flags;
-    __u32 fd;
-    __u32 unused;
-};
-
-#define MAX_HEAP_NAME 32
-
-/**
- * struct ion_heap_data - data about a heap
- * @name - first 32 characters of the heap name
- * @type - heap type
- * @heap_id - heap id for the heap
- */
-struct ion_heap_data {
-    char name[MAX_HEAP_NAME];
-    __u32 type;
-    __u32 heap_id;
-    __u32 reserved0;
-    __u32 reserved1;
-    __u32 reserved2;
-};
-
-/**
- * struct ion_heap_query - collection of data about all heaps
- * @cnt - total number of heaps to be copied
- * @heaps - buffer to copy heap data
- */
-struct ion_heap_query {
-    __u32 cnt;       /* Total number of heaps to be copied */
-    __u32 reserved0; /* align to 64bits */
-    __u64 heaps;     /* buffer to be populated */
-    __u32 reserved1;
-    __u32 reserved2;
-};
-
-#define ION_IOC_MAGIC 'I'
-
-/**
- * DOC: ION_IOC_NEW_ALLOC - allocate memory
- *
- * Takes an ion_allocation_data struct and returns it with the handle field
- * populated with the opaque handle for the allocation.
- * TODO: This IOCTL will clash by design; however, only one of
- *  ION_IOC_ALLOC or ION_IOC_NEW_ALLOC paths will be exercised,
- *  so this should not conflict.
- */
-#define ION_IOC_NEW_ALLOC _IOWR(ION_IOC_MAGIC, 0, struct ion_new_allocation_data)
-
-/**
- * DOC: ION_IOC_FREE - free memory
- *
- * Takes an ion_handle_data struct and frees the handle.
- *
- * #define ION_IOC_FREE		_IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
- * This will come from the older kernels, so don't redefine here
- */
-
-/**
- * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
- *
- * Takes an ion_fd_data struct with the handle field populated with a valid
- * opaque handle.  Returns the struct with the fd field set to a file
- * descriptor open in the current address space.  This file descriptor
- * can then be passed to another process.  The corresponding opaque handle can
- * be retrieved via ION_IOC_IMPORT.
- *
- * #define ION_IOC_SHARE		_IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
- * This will come from the older kernels, so don't redefine here
- */
-
-/**
- * DOC: ION_IOC_HEAP_QUERY - information about available heaps
- *
- * Takes an ion_heap_query structure and populates information about
- * available Ion heaps.
- */
-#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, struct ion_heap_query)
-
-#endif /* _UAPI_LINUX_ION_NEW_H */
diff --git a/libion/ion_test.c b/libion/ion_test.c
deleted file mode 100644
index f3874ae..0000000
--- a/libion/ion_test.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- *   Copyright 2013 Google, Inc
- *
- *  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 <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <ion/ion.h>
-#include <linux/ion.h>
-
-size_t len = 1024*1024, align = 0;
-int prot = PROT_READ | PROT_WRITE;
-int map_flags = MAP_SHARED;
-int alloc_flags = 0;
-int heap_mask = 1;
-int test = -1;
-size_t stride;
-
-int _ion_alloc_test(int *fd, ion_user_handle_t *handle)
-{
-    int ret;
-
-    *fd = ion_open();
-    if (*fd < 0)
-        return *fd;
-
-    ret = ion_alloc(*fd, len, align, heap_mask, alloc_flags, handle);
-
-    if (ret)
-        printf("%s failed: %s\n", __func__, strerror(ret));
-    return ret;
-}
-
-void ion_alloc_test()
-{
-    int fd, ret;
-    ion_user_handle_t handle;
-
-    if(_ion_alloc_test(&fd, &handle))
-        return;
-
-    ret = ion_free(fd, handle);
-    if (ret) {
-        printf("%s failed: %s %d\n", __func__, strerror(ret), handle);
-        return;
-    }
-    ion_close(fd);
-    printf("ion alloc test: passed\n");
-}
-
-void ion_map_test()
-{
-    int fd, map_fd, ret;
-    size_t i;
-    ion_user_handle_t handle;
-    unsigned char *ptr;
-
-    if(_ion_alloc_test(&fd, &handle))
-        return;
-
-    ret = ion_map(fd, handle, len, prot, map_flags, 0, &ptr, &map_fd);
-    if (ret)
-        return;
-
-    for (i = 0; i < len; i++) {
-        ptr[i] = (unsigned char)i;
-    }
-    for (i = 0; i < len; i++)
-        if (ptr[i] != (unsigned char)i)
-            printf("%s failed wrote %zu read %d from mapped "
-                   "memory\n", __func__, i, ptr[i]);
-    /* clean up properly */
-    ret = ion_free(fd, handle);
-    ion_close(fd);
-    munmap(ptr, len);
-    close(map_fd);
-
-    _ion_alloc_test(&fd, &handle);
-    close(fd);
-
-#if 0
-    munmap(ptr, len);
-    close(map_fd);
-    ion_close(fd);
-
-    _ion_alloc_test(len, align, flags, &fd, &handle);
-    close(map_fd);
-    ret = ion_map(fd, handle, len, prot, flags, 0, &ptr, &map_fd);
-    /* don't clean up */
-#endif
-}
-
-void ion_share_test()
-
-{
-    ion_user_handle_t handle;
-    int sd[2];
-    int num_fd = 1;
-    struct iovec count_vec = {
-        .iov_base = &num_fd,
-        .iov_len = sizeof num_fd,
-    };
-    char buf[CMSG_SPACE(sizeof(int))];
-    socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
-    if (fork()) {
-        struct msghdr msg = {
-            .msg_control = buf,
-            .msg_controllen = sizeof buf,
-            .msg_iov = &count_vec,
-            .msg_iovlen = 1,
-        };
-
-        struct cmsghdr *cmsg;
-        int fd, share_fd, ret;
-        char *ptr;
-        /* parent */
-        if(_ion_alloc_test(&fd, &handle))
-            return;
-        ret = ion_share(fd, handle, &share_fd);
-        if (ret)
-            printf("share failed %s\n", strerror(errno));
-        ptr = mmap(NULL, len, prot, map_flags, share_fd, 0);
-        if (ptr == MAP_FAILED) {
-            return;
-        }
-        strcpy(ptr, "master");
-        cmsg = CMSG_FIRSTHDR(&msg);
-        cmsg->cmsg_level = SOL_SOCKET;
-        cmsg->cmsg_type = SCM_RIGHTS;
-        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-        *(int *)CMSG_DATA(cmsg) = share_fd;
-        /* send the fd */
-        printf("master? [%10s] should be [master]\n", ptr);
-        printf("master sending msg 1\n");
-        sendmsg(sd[0], &msg, 0);
-        if (recvmsg(sd[0], &msg, 0) < 0)
-            perror("master recv msg 2");
-        printf("master? [%10s] should be [child]\n", ptr);
-
-        /* send ping */
-        sendmsg(sd[0], &msg, 0);
-        printf("master->master? [%10s]\n", ptr);
-        if (recvmsg(sd[0], &msg, 0) < 0)
-            perror("master recv 1");
-        close(fd);
-        _exit(0);
-    } else {
-        struct cmsghdr *cmsg;
-        char* ptr;
-        int fd, recv_fd;
-        char* child_buf[100];
-        /* child */
-        struct iovec count_vec = {
-            .iov_base = child_buf,
-            .iov_len = sizeof child_buf,
-        };
-
-        struct msghdr child_msg = {
-            .msg_control = buf,
-            .msg_controllen = sizeof buf,
-            .msg_iov = &count_vec,
-            .msg_iovlen = 1,
-        };
-
-        if (recvmsg(sd[1], &child_msg, 0) < 0)
-            perror("child recv msg 1");
-        cmsg = CMSG_FIRSTHDR(&child_msg);
-        if (cmsg == NULL) {
-            printf("no cmsg rcvd in child");
-            return;
-        }
-        recv_fd = *(int*)CMSG_DATA(cmsg);
-        if (recv_fd < 0) {
-            printf("could not get recv_fd from socket");
-            return;
-        }
-        printf("child %d\n", recv_fd);
-        fd = ion_open();
-        ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0);
-        if (ptr == MAP_FAILED) {
-            return;
-        }
-        printf("child? [%10s] should be [master]\n", ptr);
-        strcpy(ptr, "child");
-        printf("child sending msg 2\n");
-        sendmsg(sd[1], &child_msg, 0);
-        close(fd);
-    }
-}
-
-int main(int argc, char* argv[]) {
-    int c;
-    enum tests {
-        ALLOC_TEST = 0, MAP_TEST, SHARE_TEST,
-    };
-
-    while (1) {
-        static struct option opts[] = {
-            {"alloc", no_argument, 0, 'a'},
-            {"alloc_flags", required_argument, 0, 'f'},
-            {"heap_mask", required_argument, 0, 'h'},
-            {"map", no_argument, 0, 'm'},
-            {"share", no_argument, 0, 's'},
-            {"len", required_argument, 0, 'l'},
-            {"align", required_argument, 0, 'g'},
-            {"map_flags", required_argument, 0, 'z'},
-            {"prot", required_argument, 0, 'p'},
-        };
-        int i = 0;
-        c = getopt_long(argc, argv, "af:h:l:mr:st", opts, &i);
-        if (c == -1)
-            break;
-
-        switch (c) {
-        case 'l':
-            len = atol(optarg);
-            break;
-        case 'g':
-            align = atol(optarg);
-            break;
-        case 'z':
-            map_flags = 0;
-            map_flags |= strstr(optarg, "PROT_EXEC") ? PROT_EXEC : 0;
-            map_flags |= strstr(optarg, "PROT_READ") ? PROT_READ: 0;
-            map_flags |= strstr(optarg, "PROT_WRITE") ? PROT_WRITE: 0;
-            map_flags |= strstr(optarg, "PROT_NONE") ? PROT_NONE: 0;
-            break;
-        case 'p':
-            prot = 0;
-            prot |= strstr(optarg, "MAP_PRIVATE") ? MAP_PRIVATE : 0;
-            prot |= strstr(optarg, "MAP_SHARED") ? MAP_SHARED : 0;
-            break;
-        case 'f':
-            alloc_flags = atol(optarg);
-            break;
-        case 'h':
-            heap_mask = atol(optarg);
-            break;
-        case 'a':
-            test = ALLOC_TEST;
-            break;
-        case 'm':
-            test = MAP_TEST;
-            break;
-        case 's':
-            test = SHARE_TEST;
-            break;
-        }
-    }
-    printf("test %d, len %zu, align %zu, map_flags %d, prot %d, heap_mask %d,"
-           " alloc_flags %d\n", test, len, align, map_flags, prot,
-           heap_mask, alloc_flags);
-    switch (test) {
-        case ALLOC_TEST:
-            ion_alloc_test();
-            break;
-        case MAP_TEST:
-            ion_map_test();
-            break;
-        case SHARE_TEST:
-            ion_share_test();
-            break;
-        default:
-            printf("must specify a test (alloc, map, share)\n");
-    }
-    return 0;
-}
diff --git a/libion/kernel-headers/linux/ion.h b/libion/kernel-headers/linux/ion.h
deleted file mode 100644
index 3c28080..0000000
--- a/libion/kernel-headers/linux/ion.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _UAPI_LINUX_ION_H
-#define _UAPI_LINUX_ION_H
-#include <linux/ioctl.h>
-#include <linux/types.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-typedef int ion_user_handle_t;
-enum ion_heap_type {
- ION_HEAP_TYPE_SYSTEM,
- ION_HEAP_TYPE_SYSTEM_CONTIG,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- ION_HEAP_TYPE_CARVEOUT,
- ION_HEAP_TYPE_CHUNK,
- ION_HEAP_TYPE_DMA,
- ION_HEAP_TYPE_CUSTOM,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- ION_NUM_HEAPS = 16,
-};
-#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
-#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
-#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
-#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
-#define ION_FLAG_CACHED 1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ION_FLAG_CACHED_NEEDS_SYNC 2
-struct ion_allocation_data {
- size_t len;
- size_t align;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned int heap_id_mask;
- unsigned int flags;
- ion_user_handle_t handle;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct ion_fd_data {
- ion_user_handle_t handle;
- int fd;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct ion_handle_data {
- ion_user_handle_t handle;
-};
-struct ion_custom_data {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned int cmd;
- unsigned long arg;
-};
-#define ION_IOC_MAGIC 'I'
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0,   struct ion_allocation_data)
-#define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
-#define ION_IOC_MAP _IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
-#define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
-#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
-#define ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libion/kernel-headers/linux/ion_test.h b/libion/kernel-headers/linux/ion_test.h
deleted file mode 100644
index 6f3e2a7..0000000
--- a/libion/kernel-headers/linux/ion_test.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _UAPI_LINUX_ION_TEST_H
-#define _UAPI_LINUX_ION_TEST_H
-#include <linux/ioctl.h>
-#include <linux/types.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct ion_test_rw_data {
- __u64 ptr;
- __u64 offset;
- __u64 size;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- int write;
- int __padding;
-};
-#define ION_IOC_MAGIC 'I'
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define ION_IOC_TEST_SET_FD   _IO(ION_IOC_MAGIC, 0xf0)
-#define ION_IOC_TEST_DMA_MAPPING   _IOW(ION_IOC_MAGIC, 0xf1, struct ion_test_rw_data)
-#define ION_IOC_TEST_KERNEL_MAPPING   _IOW(ION_IOC_MAGIC, 0xf2, struct ion_test_rw_data)
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libion/original-kernel-headers/linux/ion.h b/libion/original-kernel-headers/linux/ion.h
deleted file mode 100644
index f09e7c1..0000000
--- a/libion/original-kernel-headers/linux/ion.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * drivers/staging/android/uapi/ion.h
- *
- * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _UAPI_LINUX_ION_H
-#define _UAPI_LINUX_ION_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-typedef int ion_user_handle_t;
-
-/**
- * enum ion_heap_types - list of all possible types of heaps
- * @ION_HEAP_TYPE_SYSTEM:	 memory allocated via vmalloc
- * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
- * @ION_HEAP_TYPE_CARVEOUT:	 memory allocated from a prereserved
- * 				 carveout heap, allocations are physically
- * 				 contiguous
- * @ION_HEAP_TYPE_DMA:		 memory allocated via DMA API
- * @ION_NUM_HEAPS:		 helper for iterating over heaps, a bit mask
- * 				 is used to identify the heaps, so only 32
- * 				 total heap types are supported
- */
-enum ion_heap_type {
-	ION_HEAP_TYPE_SYSTEM,
-	ION_HEAP_TYPE_SYSTEM_CONTIG,
-	ION_HEAP_TYPE_CARVEOUT,
-	ION_HEAP_TYPE_CHUNK,
-	ION_HEAP_TYPE_DMA,
-	ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
-				 are at the end of this enum */
-	ION_NUM_HEAPS = 16,
-};
-
-#define ION_HEAP_SYSTEM_MASK		(1 << ION_HEAP_TYPE_SYSTEM)
-#define ION_HEAP_SYSTEM_CONTIG_MASK	(1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
-#define ION_HEAP_CARVEOUT_MASK		(1 << ION_HEAP_TYPE_CARVEOUT)
-#define ION_HEAP_TYPE_DMA_MASK		(1 << ION_HEAP_TYPE_DMA)
-
-#define ION_NUM_HEAP_IDS		sizeof(unsigned int) * 8
-
-/**
- * allocation flags - the lower 16 bits are used by core ion, the upper 16
- * bits are reserved for use by the heaps themselves.
- */
-#define ION_FLAG_CACHED 1		/* mappings of this buffer should be
-					   cached, ion will do cache
-					   maintenance when the buffer is
-					   mapped for dma */
-#define ION_FLAG_CACHED_NEEDS_SYNC 2	/* mappings of this buffer will created
-					   at mmap time, if this is set
-					   caches must be managed manually */
-
-/**
- * DOC: Ion Userspace API
- *
- * create a client by opening /dev/ion
- * most operations handled via following ioctls
- *
- */
-
-/**
- * struct ion_allocation_data - metadata passed from userspace for allocations
- * @len:		size of the allocation
- * @align:		required alignment of the allocation
- * @heap_id_mask:	mask of heap ids to allocate from
- * @flags:		flags passed to heap
- * @handle:		pointer that will be populated with a cookie to use to 
- *			refer to this allocation
- *
- * Provided by userspace as an argument to the ioctl
- */
-struct ion_allocation_data {
-	size_t len;
-	size_t align;
-	unsigned int heap_id_mask;
-	unsigned int flags;
-	ion_user_handle_t handle;
-};
-
-/**
- * struct ion_fd_data - metadata passed to/from userspace for a handle/fd pair
- * @handle:	a handle
- * @fd:		a file descriptor representing that handle
- *
- * For ION_IOC_SHARE or ION_IOC_MAP userspace populates the handle field with
- * the handle returned from ion alloc, and the kernel returns the file
- * descriptor to share or map in the fd field.  For ION_IOC_IMPORT, userspace
- * provides the file descriptor and the kernel returns the handle.
- */
-struct ion_fd_data {
-	ion_user_handle_t handle;
-	int fd;
-};
-
-/**
- * struct ion_handle_data - a handle passed to/from the kernel
- * @handle:	a handle
- */
-struct ion_handle_data {
-	ion_user_handle_t handle;
-};
-
-/**
- * struct ion_custom_data - metadata passed to/from userspace for a custom ioctl
- * @cmd:	the custom ioctl function to call
- * @arg:	additional data to pass to the custom ioctl, typically a user
- *		pointer to a predefined structure
- *
- * This works just like the regular cmd and arg fields of an ioctl.
- */
-struct ion_custom_data {
-	unsigned int cmd;
-	unsigned long arg;
-};
-
-#define ION_IOC_MAGIC		'I'
-
-/**
- * DOC: ION_IOC_ALLOC - allocate memory
- *
- * Takes an ion_allocation_data struct and returns it with the handle field
- * populated with the opaque handle for the allocation.
- */
-#define ION_IOC_ALLOC		_IOWR(ION_IOC_MAGIC, 0, \
-				      struct ion_allocation_data)
-
-/**
- * DOC: ION_IOC_FREE - free memory
- *
- * Takes an ion_handle_data struct and frees the handle.
- */
-#define ION_IOC_FREE		_IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
-
-/**
- * DOC: ION_IOC_MAP - get a file descriptor to mmap
- *
- * Takes an ion_fd_data struct with the handle field populated with a valid
- * opaque handle.  Returns the struct with the fd field set to a file
- * descriptor open in the current address space.  This file descriptor
- * can then be used as an argument to mmap.
- */
-#define ION_IOC_MAP		_IOWR(ION_IOC_MAGIC, 2, struct ion_fd_data)
-
-/**
- * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
- *
- * Takes an ion_fd_data struct with the handle field populated with a valid
- * opaque handle.  Returns the struct with the fd field set to a file
- * descriptor open in the current address space.  This file descriptor
- * can then be passed to another process.  The corresponding opaque handle can
- * be retrieved via ION_IOC_IMPORT.
- */
-#define ION_IOC_SHARE		_IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
-
-/**
- * DOC: ION_IOC_IMPORT - imports a shared file descriptor
- *
- * Takes an ion_fd_data struct with the fd field populated with a valid file
- * descriptor obtained from ION_IOC_SHARE and returns the struct with the handle
- * filed set to the corresponding opaque handle.
- */
-#define ION_IOC_IMPORT		_IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
-
-/**
- * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory
- *
- * Deprecated in favor of using the dma_buf api's correctly (syncing
- * will happend automatically when the buffer is mapped to a device).
- * If necessary should be used after touching a cached buffer from the cpu,
- * this will make the buffer in memory coherent.
- */
-#define ION_IOC_SYNC		_IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
-
-/**
- * DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl
- *
- * Takes the argument of the architecture specific ioctl to call and
- * passes appropriate userdata for that ioctl
- */
-#define ION_IOC_CUSTOM		_IOWR(ION_IOC_MAGIC, 6, struct ion_custom_data)
-
-#endif /* _UAPI_LINUX_ION_H */
diff --git a/libion/original-kernel-headers/linux/ion_test.h b/libion/original-kernel-headers/linux/ion_test.h
deleted file mode 100644
index ffef06f..0000000
--- a/libion/original-kernel-headers/linux/ion_test.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * drivers/staging/android/uapi/ion.h
- *
- * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _UAPI_LINUX_ION_TEST_H
-#define _UAPI_LINUX_ION_TEST_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/**
- * struct ion_test_rw_data - metadata passed to the kernel to read handle
- * @ptr:	a pointer to an area at least as large as size
- * @offset:	offset into the ion buffer to start reading
- * @size:	size to read or write
- * @write:	1 to write, 0 to read
- */
-struct ion_test_rw_data {
-	__u64 ptr;
-	__u64 offset;
-	__u64 size;
-	int write;
-	int __padding;
-};
-
-#define ION_IOC_MAGIC		'I'
-
-/**
- * DOC: ION_IOC_TEST_SET_DMA_BUF - attach a dma buf to the test driver
- *
- * Attaches a dma buf fd to the test driver.  Passing a second fd or -1 will
- * release the first fd.
- */
-#define ION_IOC_TEST_SET_FD \
-			_IO(ION_IOC_MAGIC, 0xf0)
-
-/**
- * DOC: ION_IOC_TEST_DMA_MAPPING - read or write memory from a handle as DMA
- *
- * Reads or writes the memory from a handle using an uncached mapping.  Can be
- * used by unit tests to emulate a DMA engine as close as possible.  Only
- * expected to be used for debugging and testing, may not always be available.
- */
-#define ION_IOC_TEST_DMA_MAPPING \
-			_IOW(ION_IOC_MAGIC, 0xf1, struct ion_test_rw_data)
-
-/**
- * DOC: ION_IOC_TEST_KERNEL_MAPPING - read or write memory from a handle
- *
- * Reads or writes the memory from a handle using a kernel mapping.  Can be
- * used by unit tests to test heap map_kernel functions.  Only expected to be
- * used for debugging and testing, may not always be available.
- */
-#define ION_IOC_TEST_KERNEL_MAPPING \
-			_IOW(ION_IOC_MAGIC, 0xf2, struct ion_test_rw_data)
-
-
-#endif /* _UAPI_LINUX_ION_H */
diff --git a/libion/tests/Android.bp b/libion/tests/Android.bp
deleted file mode 100644
index b3fcb3b..0000000
--- a/libion/tests/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (C) 2013 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_test {
-    name: "ion-unit-tests",
-    cflags: [
-        "-g",
-        "-Wall",
-        "-Werror",
-        "-Wno-missing-field-initializers",
-    ],
-    shared_libs: ["libion"],
-    srcs: [
-        "ion_test_fixture.cpp",
-        "allocate_test.cpp",
-        "formerly_valid_handle_test.cpp",
-        "invalid_values_test.cpp",
-        "map_test.cpp",
-        "device_test.cpp",
-        "exit_test.cpp",
-    ],
-}
diff --git a/libion/tests/allocate_test.cpp b/libion/tests/allocate_test.cpp
deleted file mode 100644
index 3c4524e..0000000
--- a/libion/tests/allocate_test.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2013 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 <memory>
-#include <sys/mman.h>
-
-#include <gtest/gtest.h>
-
-#include <ion/ion.h>
-#include "ion_test_fixture.h"
-
-class Allocate : public IonAllHeapsTest {
-};
-
-TEST_F(Allocate, Allocate)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            ion_user_handle_t handle = 0;
-            ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle));
-            ASSERT_TRUE(handle != 0);
-            ASSERT_EQ(0, ion_free(m_ionFd, handle));
-        }
-    }
-}
-
-TEST_F(Allocate, AllocateCached)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            ion_user_handle_t handle = 0;
-            ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED, &handle));
-            ASSERT_TRUE(handle != 0);
-            ASSERT_EQ(0, ion_free(m_ionFd, handle));
-        }
-    }
-}
-
-TEST_F(Allocate, AllocateCachedNeedsSync)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            ion_user_handle_t handle = 0;
-            ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED_NEEDS_SYNC, &handle));
-            ASSERT_TRUE(handle != 0);
-            ASSERT_EQ(0, ion_free(m_ionFd, handle));
-        }
-    }
-}
-
-TEST_F(Allocate, RepeatedAllocate)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            ion_user_handle_t handle = 0;
-
-            for (unsigned int i = 0; i < 1024; i++) {
-                SCOPED_TRACE(::testing::Message() << "iteration " << i);
-                ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle));
-                ASSERT_TRUE(handle != 0);
-                ASSERT_EQ(0, ion_free(m_ionFd, handle));
-            }
-        }
-    }
-}
-
-TEST_F(Allocate, Zeroed)
-{
-    auto zeroes_ptr = std::make_unique<char[]>(4096);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int fds[16];
-        for (unsigned int i = 0; i < 16; i++) {
-            int map_fd = -1;
-
-            ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, 0, &map_fd));
-            ASSERT_GE(map_fd, 0);
-
-            void *ptr = NULL;
-            ptr = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, map_fd, 0);
-            ASSERT_TRUE(ptr != NULL);
-
-            memset(ptr, 0xaa, 4096);
-
-            ASSERT_EQ(0, munmap(ptr, 4096));
-            fds[i] = map_fd;
-        }
-
-        for (unsigned int i = 0; i < 16; i++) {
-            ASSERT_EQ(0, close(fds[i]));
-        }
-
-        int newIonFd = ion_open();
-        int map_fd = -1;
-
-        ASSERT_EQ(0, ion_alloc_fd(newIonFd, 4096, 0, heapMask, 0, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr = NULL;
-        ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        ASSERT_EQ(0, memcmp(ptr, zeroes_ptr.get(), 4096));
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Allocate, Large)
-{
-    for (unsigned int heapMask : m_allHeaps) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        ion_user_handle_t handle = 0;
-        ASSERT_EQ(-ENOMEM, ion_alloc(m_ionFd, 3UL*1024*1024*1024, 0, heapMask, 0, &handle));
-    }
-}
diff --git a/libion/tests/device_test.cpp b/libion/tests/device_test.cpp
deleted file mode 100644
index eb3f7b6..0000000
--- a/libion/tests/device_test.cpp
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * Copyright (C) 2013 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 <fcntl.h>
-#include <memory>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <linux/ion_test.h>
-
-#include <gtest/gtest.h>
-
-#include <ion/ion.h>
-
-#include "ion_test_fixture.h"
-
-#define ALIGN(x,y) (((x) + ((y) - 1)) & ~((y) - 1))
-
-class Device : public IonAllHeapsTest {
- public:
-    virtual void SetUp();
-    virtual void TearDown();
-    int m_deviceFd;
-    void readDMA(int fd, void *buf, size_t size);
-    void writeDMA(int fd, void *buf, size_t size);
-    void readKernel(int fd, void *buf, size_t size);
-    void writeKernel(int fd, void *buf, size_t size);
-    void blowCache();
-    void dirtyCache(void *ptr, size_t size);
-};
-
-void Device::SetUp()
-{
-    IonAllHeapsTest::SetUp();
-    m_deviceFd = open("/dev/ion-test", O_RDONLY);
-    ASSERT_GE(m_deviceFd, 0);
-}
-
-void Device::TearDown()
-{
-    ASSERT_EQ(0, close(m_deviceFd));
-    IonAllHeapsTest::TearDown();
-}
-
-void Device::readDMA(int fd, void *buf, size_t size)
-{
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
-    struct ion_test_rw_data ion_test_rw_data = {
-            .ptr = (uint64_t)buf,
-            .offset = 0,
-            .size = size,
-            .write = 0,
-    };
-
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_DMA_MAPPING, &ion_test_rw_data));
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
-}
-
-void Device::writeDMA(int fd, void *buf, size_t size)
-{
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
-    struct ion_test_rw_data ion_test_rw_data = {
-            .ptr = (uint64_t)buf,
-            .offset = 0,
-            .size = size,
-            .write = 1,
-    };
-
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_DMA_MAPPING, &ion_test_rw_data));
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
-}
-
-void Device::readKernel(int fd, void *buf, size_t size)
-{
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
-    struct ion_test_rw_data ion_test_rw_data = {
-            .ptr = (uint64_t)buf,
-            .offset = 0,
-            .size = size,
-            .write = 0,
-    };
-
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_KERNEL_MAPPING, &ion_test_rw_data));
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
-}
-
-void Device::writeKernel(int fd, void *buf, size_t size)
-{
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
-    struct ion_test_rw_data ion_test_rw_data = {
-            .ptr = (uint64_t)buf,
-            .offset = 0,
-            .size = size,
-            .write = 1,
-    };
-
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_KERNEL_MAPPING, &ion_test_rw_data));
-    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
-}
-
-void Device::blowCache()
-{
-    const size_t bigger_than_cache = 8*1024*1024;
-    void *buf1 = malloc(bigger_than_cache);
-    void *buf2 = malloc(bigger_than_cache);
-    memset(buf1, 0xaa, bigger_than_cache);
-    memcpy(buf2, buf1, bigger_than_cache);
-    free(buf1);
-    free(buf2);
-}
-
-void Device::dirtyCache(void *ptr, size_t size)
-{
-    /* try to dirty cache lines */
-    for (size_t i = size-1; i > 0; i--) {
-        ((volatile char *)ptr)[i];
-        ((char *)ptr)[i] = i;
-    }
-}
-
-TEST_F(Device, KernelReadCached)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        for (int i = 0; i < 4096; i++)
-            ((char *)ptr)[i] = i;
-
-        ((char*)buf)[4096] = 0x12;
-        readKernel(map_fd, buf, 4096);
-        ASSERT_EQ(((char*)buf)[4096], 0x12);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)buf)[i]);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, KernelWriteCached)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (int i = 0; i < 4096; i++)
-        ((char *)buf)[i] = i;
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        writeKernel(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, DMAReadCached)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        for (int i = 0; i < 4096; i++)
-            ((char *)ptr)[i] = i;
-
-        readDMA(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)buf)[i]);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, DMAWriteCached)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (int i = 0; i < 4096; i++)
-        ((char *)buf)[i] = i;
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        writeDMA(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, KernelReadCachedNeedsSync)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        for (int i = 0; i < 4096; i++)
-            ((char *)ptr)[i] = i;
-
-        ((char*)buf)[4096] = 0x12;
-        readKernel(map_fd, buf, 4096);
-        ASSERT_EQ(((char*)buf)[4096], 0x12);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)buf)[i]);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, KernelWriteCachedNeedsSync)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (int i = 0; i < 4096; i++)
-        ((char *)buf)[i] = i;
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        writeKernel(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, DMAReadCachedNeedsSync)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        for (int i = 0; i < 4096; i++)
-            ((char *)ptr)[i] = i;
-
-        ion_sync_fd(m_ionFd, map_fd);
-
-        readDMA(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)buf)[i]);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, DMAWriteCachedNeedsSync)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (int i = 0; i < 4096; i++)
-        ((char *)buf)[i] = i;
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        writeDMA(map_fd, buf, 4096);
-
-        ion_sync_fd(m_ionFd, map_fd);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-TEST_F(Device, KernelRead)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = 0;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        for (int i = 0; i < 4096; i++)
-            ((char *)ptr)[i] = i;
-
-        ((char*)buf)[4096] = 0x12;
-        readKernel(map_fd, buf, 4096);
-        ASSERT_EQ(((char*)buf)[4096], 0x12);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)buf)[i]);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, KernelWrite)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (int i = 0; i < 4096; i++)
-        ((char *)buf)[i] = i;
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = 0;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        writeKernel(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, DMARead)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = 0;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        for (int i = 0; i < 4096; i++)
-            ((char *)ptr)[i] = i;
-
-        readDMA(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)buf)[i]);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, DMAWrite)
-{
-    auto alloc_ptr = std::make_unique<char[]>(8192 + 1024);
-    void *buf = (void *)(ALIGN((unsigned long)alloc_ptr.get(), 4096) + 1024);
-
-    for (int i = 0; i < 4096; i++)
-        ((char *)buf)[i] = i;
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = 0;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        writeDMA(map_fd, buf, 4096);
-
-        for (int i = 0; i < 4096; i++)
-            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Device, IsCached)
-{
-    auto buf_ptr = std::make_unique<char[]>(4096);
-    void *buf = buf_ptr.get();
-
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        void *ptr;
-        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        dirtyCache(ptr, 4096);
-
-        readDMA(map_fd, buf, 4096);
-
-        bool same = true;
-        for (int i = 4096-16; i >= 0; i -= 16)
-            if (((char *)buf)[i] != i)
-                same = false;
-        ASSERT_FALSE(same);
-
-        ASSERT_EQ(0, munmap(ptr, 4096));
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
diff --git a/libion/tests/exit_test.cpp b/libion/tests/exit_test.cpp
deleted file mode 100644
index cdd3e27..0000000
--- a/libion/tests/exit_test.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright (C) 2013 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 <sys/mman.h>
-
-#include <gtest/gtest.h>
-
-#include <ion/ion.h>
-
-#include "ion_test_fixture.h"
-
-class Exit : public IonAllHeapsTest {
-};
-
-TEST_F(Exit, WithAlloc)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                ion_user_handle_t handle = 0;
-
-                ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle));
-                ASSERT_TRUE(handle != 0);
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-}
-
-TEST_F(Exit, WithAllocFd)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int handle_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &handle_fd));
-                ASSERT_NE(-1, handle_fd);
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-}
-
-TEST_F(Exit, WithRepeatedAllocFd)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            for (unsigned int i = 0; i < 1024; i++) {
-                SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-                SCOPED_TRACE(::testing::Message() << "size " << size);
-                ASSERT_EXIT({
-                    int handle_fd = -1;
-
-                    ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &handle_fd));
-                    ASSERT_NE(-1, handle_fd);
-                    exit(0);
-                }, ::testing::ExitedWithCode(0), "")
-                        << "failed on heap " << heapMask
-                        << " and size " << size
-                        << " on iteration " << i;
-            }
-        }
-    }
-}
-
-
-TEST_F(Exit, WithMapping)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int map_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &map_fd));
-                ASSERT_GE(map_fd, 0);
-
-                void *ptr;
-                ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-                ASSERT_TRUE(ptr != NULL);
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-
-}
-
-TEST_F(Exit, WithPartialMapping)
-{
-    static const size_t allocationSizes[] = {64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int map_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &map_fd));
-                ASSERT_GE(map_fd, 0);
-
-                void *ptr;
-                ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-                ASSERT_TRUE(ptr != NULL);
-
-                ASSERT_EQ(0, munmap(ptr, size / 2));
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-}
-
-TEST_F(Exit, WithMappingCached)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int map_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED, &map_fd));
-                ASSERT_GE(map_fd, 0);
-
-                void *ptr;
-                ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-                ASSERT_TRUE(ptr != NULL);
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-
-}
-
-TEST_F(Exit, WithPartialMappingCached)
-{
-    static const size_t allocationSizes[] = {64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int map_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED, &map_fd));
-                ASSERT_GE(map_fd, 0);
-
-                void *ptr;
-                ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-                ASSERT_TRUE(ptr != NULL);
-
-                ASSERT_EQ(0, munmap(ptr, size / 2));
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-}
-
-TEST_F(Exit, WithMappingNeedsSync)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int map_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC, &map_fd));
-                ASSERT_GE(map_fd, 0);
-
-                void *ptr;
-                ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-                ASSERT_TRUE(ptr != NULL);
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-
-}
-
-TEST_F(Exit, WithPartialMappingNeedsSync)
-{
-    static const size_t allocationSizes[] = {64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            EXPECT_EXIT({
-                int map_fd = -1;
-
-                ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC, &map_fd));
-                ASSERT_GE(map_fd, 0);
-
-                void *ptr;
-                ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-                ASSERT_TRUE(ptr != NULL);
-
-                ASSERT_EQ(0, munmap(ptr, size / 2));
-                exit(0);
-            }, ::testing::ExitedWithCode(0), "");
-        }
-    }
-}
diff --git a/libion/tests/formerly_valid_handle_test.cpp b/libion/tests/formerly_valid_handle_test.cpp
deleted file mode 100644
index 01ab8f3..0000000
--- a/libion/tests/formerly_valid_handle_test.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2013 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 <sys/mman.h>
-
-#include <gtest/gtest.h>
-
-#include <ion/ion.h>
-
-#include "ion_test_fixture.h"
-
-class FormerlyValidHandle : public IonTest {
- public:
-    virtual void SetUp();
-    virtual void TearDown();
-    ion_user_handle_t m_handle;
-};
-
-void FormerlyValidHandle::SetUp()
-{
-    IonTest::SetUp();
-    ASSERT_EQ(0, ion_alloc(m_ionFd, 4096, 0, 1/* ion_env->m_firstHeap */, 0, &m_handle));
-    ASSERT_TRUE(m_handle != 0);
-    ASSERT_EQ(0, ion_free(m_ionFd, m_handle));
-}
-
-void FormerlyValidHandle::TearDown()
-{
-    m_handle = 0;
-}
-
-TEST_F(FormerlyValidHandle, free)
-{
-	ASSERT_EQ(-EINVAL, ion_free(m_ionFd, m_handle));
-}
-
-TEST_F(FormerlyValidHandle, map)
-{
-    int map_fd;
-    unsigned char *ptr;
-
-    ASSERT_EQ(-EINVAL, ion_map(m_ionFd, m_handle, 4096, PROT_READ, 0, 0, &ptr, &map_fd));
-}
-
-TEST_F(FormerlyValidHandle, share)
-{
-    int share_fd;
-
-    ASSERT_EQ(-EINVAL, ion_share(m_ionFd, m_handle, &share_fd));
-}
diff --git a/libion/tests/invalid_values_test.cpp b/libion/tests/invalid_values_test.cpp
deleted file mode 100644
index 77fea17..0000000
--- a/libion/tests/invalid_values_test.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2013 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 <sys/mman.h>
-
-#include <gtest/gtest.h>
-
-#include <ion/ion.h>
-
-#include "ion_test_fixture.h"
-
-class InvalidValues : public IonAllHeapsTest {
- public:
-    virtual void SetUp();
-    virtual void TearDown();
-    ion_user_handle_t m_validHandle;
-    int m_validShareFd;
-    ion_user_handle_t const m_badHandle = -1;
-};
-
-void InvalidValues::SetUp()
-{
-    IonAllHeapsTest::SetUp();
-    ASSERT_EQ(0, ion_alloc(m_ionFd, 4096, 0, m_firstHeap, 0, &m_validHandle))
-      << m_ionFd << " " << m_firstHeap;
-    ASSERT_TRUE(m_validHandle != 0);
-    ASSERT_EQ(0, ion_share(m_ionFd, m_validHandle, &m_validShareFd));
-}
-
-void InvalidValues::TearDown()
-{
-    ASSERT_EQ(0, ion_free(m_ionFd, m_validHandle));
-    ASSERT_EQ(0, close(m_validShareFd));
-    m_validHandle = 0;
-    IonAllHeapsTest::TearDown();
-}
-
-TEST_F(InvalidValues, ion_close)
-{
-    EXPECT_EQ(-EBADF, ion_close(-1));
-}
-
-TEST_F(InvalidValues, ion_alloc)
-{
-    ion_user_handle_t handle;
-    /* invalid ion_fd */
-    int ret = ion_alloc(0, 4096, 0, m_firstHeap, 0, &handle);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion_fd */
-    EXPECT_EQ(-EBADF, ion_alloc(-1, 4096, 0, m_firstHeap, 0, &handle));
-    /* no heaps */
-    EXPECT_EQ(-ENODEV, ion_alloc(m_ionFd, 4096, 0, 0, 0, &handle));
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        /* zero size */
-        EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, 0, 0, heapMask, 0, &handle));
-        /* too large size */
-        EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, -1, 0, heapMask, 0, &handle));
-        /* bad alignment */
-        EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, 4096, -1, heapMask, 0, &handle));
-        /* NULL handle */
-        EXPECT_EQ(-EINVAL, ion_alloc(m_ionFd, 4096, 0, heapMask, 0, NULL));
-    }
-}
-
-TEST_F(InvalidValues, ion_alloc_fd)
-{
-    int fd;
-    /* invalid ion_fd */
-    int ret = ion_alloc_fd(0, 4096, 0, m_firstHeap, 0, &fd);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion_fd */
-    EXPECT_EQ(-EBADF, ion_alloc_fd(-1, 4096, 0, m_firstHeap, 0, &fd));
-    /* no heaps */
-    EXPECT_EQ(-ENODEV, ion_alloc_fd(m_ionFd, 4096, 0, 0, 0, &fd));
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        /* zero size */
-        EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, 0, 0, heapMask, 0, &fd));
-        /* too large size */
-        EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, -1, 0, heapMask, 0, &fd));
-        /* bad alignment */
-        EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, 4096, -1, heapMask, 0, &fd));
-        /* NULL handle */
-        EXPECT_EQ(-EINVAL, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, 0, NULL));
-    }
-}
-
-TEST_F(InvalidValues, ion_free)
-{
-    /* invalid ion fd */
-    int ret = ion_free(0, m_validHandle);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion fd */
-    EXPECT_EQ(-EBADF, ion_free(-1, m_validHandle));
-    /* zero handle */
-    EXPECT_EQ(-EINVAL, ion_free(m_ionFd, 0));
-    /* bad handle */
-    EXPECT_EQ(-EINVAL, ion_free(m_ionFd, m_badHandle));
-}
-
-TEST_F(InvalidValues, ion_map)
-{
-    int map_fd;
-    unsigned char *ptr;
-
-    /* invalid ion fd */
-    int ret = ion_map(0, m_validHandle, 4096, PROT_READ, 0, 0, &ptr, &map_fd);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion fd */
-    EXPECT_EQ(-EBADF, ion_map(-1, m_validHandle, 4096, PROT_READ, 0, 0, &ptr, &map_fd));
-    /* zero handle */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, 0, 4096, PROT_READ, 0, 0, &ptr, &map_fd));
-    /* bad handle */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_badHandle, 4096, PROT_READ, 0, 0, &ptr, &map_fd));
-    /* zero length */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 0, PROT_READ, 0, 0, &ptr, &map_fd));
-    /* bad prot */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, -1, 0, 0, &ptr, &map_fd));
-    /* bad offset */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, PROT_READ, 0, -1, &ptr, &map_fd));
-    /* NULL ptr */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, PROT_READ, 0, 0, NULL, &map_fd));
-    /* NULL map_fd */
-    EXPECT_EQ(-EINVAL, ion_map(m_ionFd, m_validHandle, 4096, PROT_READ, 0, 0, &ptr, NULL));
-}
-
-TEST_F(InvalidValues, ion_share)
-{
-    int share_fd;
-
-    /* invalid ion fd */
-    int ret = ion_share(0, m_validHandle, &share_fd);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion fd */
-    EXPECT_EQ(-EBADF, ion_share(-1, m_validHandle, &share_fd));
-    /* zero handle */
-    EXPECT_EQ(-EINVAL, ion_share(m_ionFd, 0, &share_fd));
-    /* bad handle */
-    EXPECT_EQ(-EINVAL, ion_share(m_ionFd, m_badHandle, &share_fd));
-    /* NULL share_fd */
-    EXPECT_EQ(-EINVAL, ion_share(m_ionFd, m_validHandle, NULL));
-}
-
-TEST_F(InvalidValues, ion_import)
-{
-    ion_user_handle_t handle;
-
-    /* invalid ion fd */
-    int ret = ion_import(0, m_validShareFd, &handle);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion fd */
-    EXPECT_EQ(-EBADF, ion_import(-1, m_validShareFd, &handle));
-    /* bad share_fd */
-    EXPECT_EQ(-EINVAL, ion_import(m_ionFd, 0, &handle));
-    /* invalid share_fd */
-    EXPECT_EQ(-EBADF, ion_import(m_ionFd, -1, &handle));
-    /* NULL handle */
-    EXPECT_EQ(-EINVAL, ion_import(m_ionFd, m_validShareFd, NULL));
-}
-
-TEST_F(InvalidValues, ion_sync_fd)
-{
-    /* invalid ion fd */
-    int ret = ion_sync_fd(0, m_validShareFd);
-    EXPECT_TRUE(ret == -EINVAL || ret == -ENOTTY);
-    /* invalid ion fd */
-    EXPECT_EQ(-EBADF, ion_sync_fd(-1, m_validShareFd));
-    /* bad share_fd */
-    EXPECT_EQ(-EINVAL, ion_sync_fd(m_ionFd, 0));
-    /* invalid share_fd */
-    EXPECT_EQ(-EBADF, ion_sync_fd(m_ionFd, -1));
-}
diff --git a/libion/tests/ion_test_fixture.cpp b/libion/tests/ion_test_fixture.cpp
deleted file mode 100644
index e20c730..0000000
--- a/libion/tests/ion_test_fixture.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013 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 <ion/ion.h>
-
-#include "ion_test_fixture.h"
-
-IonTest::IonTest() : m_ionFd(-1)
-{
-}
-
-void IonTest::SetUp() {
-    m_ionFd = ion_open();
-    ASSERT_GE(m_ionFd, 0);
-}
-
-void IonTest::TearDown() {
-    ion_close(m_ionFd);
-}
-
-IonAllHeapsTest::IonAllHeapsTest() :
-        m_firstHeap(0),
-        m_lastHeap(0),
-        m_allHeaps()
-{
-}
-
-void IonAllHeapsTest::SetUp() {
-    int fd = ion_open();
-    ASSERT_GE(fd, 0);
-
-    for (int i = 1; i != 0; i <<= 1) {
-        ion_user_handle_t handle = 0;
-        int ret;
-        ret = ion_alloc(fd, 4096, 0, i, 0, &handle);
-        if (ret == 0 && handle != 0) {
-            ion_free(fd, handle);
-            if (!m_firstHeap) {
-                m_firstHeap = i;
-            }
-            m_lastHeap = i;
-            m_allHeaps.push_back(i);
-        } else {
-            ASSERT_EQ(-ENODEV, ret);
-        }
-    }
-    ion_close(fd);
-
-    EXPECT_NE(0U, m_firstHeap);
-    EXPECT_NE(0U, m_lastHeap);
-
-    RecordProperty("Heaps", m_allHeaps.size());
-    IonTest::SetUp();
-}
-
-void IonAllHeapsTest::TearDown() {
-    IonTest::TearDown();
-}
diff --git a/libion/tests/ion_test_fixture.h b/libion/tests/ion_test_fixture.h
deleted file mode 100644
index 4098214..0000000
--- a/libion/tests/ion_test_fixture.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013 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 ION_TEST_FIXTURE_H_
-#define ION_TEST_FIXTURE_H_
-
-#include <gtest/gtest.h>
-
-using ::testing::Test;
-
-class IonTest : public virtual Test {
- public:
-    IonTest();
-	virtual ~IonTest() {};
-	virtual void SetUp();
-	virtual void TearDown();
-	int m_ionFd;
-};
-
-class IonAllHeapsTest : public IonTest {
- public:
-    IonAllHeapsTest();
-    virtual ~IonAllHeapsTest() {};
-    virtual void SetUp();
-    virtual void TearDown();
-
-    unsigned int m_firstHeap;
-    unsigned int m_lastHeap;
-
-    std::vector<unsigned int> m_allHeaps;
-};
-
-#endif /* ION_TEST_FIXTURE_H_ */
diff --git a/libion/tests/map_test.cpp b/libion/tests/map_test.cpp
deleted file mode 100644
index c006dc8..0000000
--- a/libion/tests/map_test.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2013 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 <sys/mman.h>
-
-#include <gtest/gtest.h>
-
-#include <ion/ion.h>
-
-#include "ion_test_fixture.h"
-
-class Map : public IonAllHeapsTest {
-};
-
-TEST_F(Map, MapHandle)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            ion_user_handle_t handle = 0;
-
-            ASSERT_EQ(0, ion_alloc(m_ionFd, size, 0, heapMask, 0, &handle));
-            ASSERT_TRUE(handle != 0);
-
-            int map_fd = -1;
-            unsigned char *ptr = NULL;
-            ASSERT_EQ(0, ion_map(m_ionFd, handle, size, PROT_READ | PROT_WRITE, MAP_SHARED, 0, &ptr, &map_fd));
-            ASSERT_TRUE(ptr != NULL);
-            ASSERT_GE(map_fd, 0);
-
-            ASSERT_EQ(0, close(map_fd));
-
-            ASSERT_EQ(0, ion_free(m_ionFd, handle));
-
-            memset(ptr, 0xaa, size);
-
-            ASSERT_EQ(0, munmap(ptr, size));
-        }
-    }
-}
-
-TEST_F(Map, MapFd)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            int map_fd = -1;
-
-            ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, 0, &map_fd));
-            ASSERT_GE(map_fd, 0);
-
-            void *ptr;
-            ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-            ASSERT_TRUE(ptr != NULL);
-
-            ASSERT_EQ(0, close(map_fd));
-
-            memset(ptr, 0xaa, size);
-
-            ASSERT_EQ(0, munmap(ptr, size));
-        }
-    }
-}
-
-TEST_F(Map, MapOffset)
-{
-    for (unsigned int heapMask : m_allHeaps) {
-        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-        int map_fd = -1;
-
-        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, PAGE_SIZE * 2, 0, heapMask, 0, &map_fd));
-        ASSERT_GE(map_fd, 0);
-
-        unsigned char *ptr;
-        ptr = (unsigned char *)mmap(NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-        ASSERT_TRUE(ptr != NULL);
-
-        memset(ptr, 0, PAGE_SIZE);
-        memset(ptr + PAGE_SIZE, 0xaa, PAGE_SIZE);
-
-        ASSERT_EQ(0, munmap(ptr, PAGE_SIZE * 2));
-
-        ptr = (unsigned char *)mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, PAGE_SIZE);
-        ASSERT_TRUE(ptr != NULL);
-
-        ASSERT_EQ(ptr[0], 0xaa);
-        ASSERT_EQ(ptr[PAGE_SIZE - 1], 0xaa);
-
-        ASSERT_EQ(0, munmap(ptr, PAGE_SIZE));
-
-        ASSERT_EQ(0, close(map_fd));
-    }
-}
-
-TEST_F(Map, MapCached)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            int map_fd = -1;
-            unsigned int flags = ION_FLAG_CACHED;
-
-            ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, flags, &map_fd));
-            ASSERT_GE(map_fd, 0);
-
-            void *ptr;
-            ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-            ASSERT_TRUE(ptr != NULL);
-
-            ASSERT_EQ(0, close(map_fd));
-
-            memset(ptr, 0xaa, size);
-
-            ASSERT_EQ(0, munmap(ptr, size));
-        }
-    }
-}
-
-TEST_F(Map, MapCachedNeedsSync)
-{
-    static const size_t allocationSizes[] = {4*1024, 64*1024, 1024*1024, 2*1024*1024};
-    for (unsigned int heapMask : m_allHeaps) {
-        for (size_t size : allocationSizes) {
-            SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
-            SCOPED_TRACE(::testing::Message() << "size " << size);
-            int map_fd = -1;
-            unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
-
-            ASSERT_EQ(0, ion_alloc_fd(m_ionFd, size, 0, heapMask, flags, &map_fd));
-            ASSERT_GE(map_fd, 0);
-
-            void *ptr;
-            ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
-            ASSERT_TRUE(ptr != NULL);
-
-            ASSERT_EQ(0, close(map_fd));
-
-            memset(ptr, 0xaa, size);
-
-            ASSERT_EQ(0, munmap(ptr, size));
-        }
-    }
-}
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index dda491a..b388e95 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -16,17 +16,3 @@
     srcs: ["keyutils_test.cpp"],
     test_suites: ["device-tests"],
 }
-
-cc_binary {
-    name: "mini-keyctl",
-    srcs: [
-        "mini_keyctl.cpp",
-        "mini_keyctl_utils.cpp"
-    ],
-    shared_libs: [
-        "libbase",
-        "libkeyutils",
-        "liblog",
-    ],
-    cflags: ["-Werror", "-Wall", "-Wextra", "-fexceptions"],
-}
diff --git a/libkeyutils/mini_keyctl.cpp b/libkeyutils/mini_keyctl.cpp
deleted file mode 100644
index fe89e62..0000000
--- a/libkeyutils/mini_keyctl.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * A tool loads keys to keyring.
- */
-
-#include "mini_keyctl_utils.h"
-
-#include <error.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <android-base/parseint.h>
-
-static void Usage(int exit_code) {
-  fprintf(stderr, "usage: mini-keyctl <action> [args,]\n");
-  fprintf(stderr, "       mini-keyctl add <type> <desc> <data> <keyring>\n");
-  fprintf(stderr, "       mini-keyctl padd <type> <desc> <keyring>\n");
-  fprintf(stderr, "       mini-keyctl unlink <key> <keyring>\n");
-  fprintf(stderr, "       mini-keyctl restrict_keyring <keyring>\n");
-  fprintf(stderr, "       mini-keyctl security <key>\n");
-  _exit(exit_code);
-}
-
-static key_serial_t parseKeyOrDie(const char* str) {
-  key_serial_t key;
-  if (!android::base::ParseInt(str, &key)) {
-    error(1 /* exit code */, 0 /* errno */, "Unparsable key: '%s'\n", str);
-  }
-  return key;
-}
-
-int main(int argc, const char** argv) {
-  if (argc < 2) Usage(1);
-  const std::string action = argv[1];
-
-  if (action == "add") {
-    if (argc != 6) Usage(1);
-    std::string type = argv[2];
-    std::string desc = argv[3];
-    std::string data = argv[4];
-    std::string keyring = argv[5];
-    return Add(type, desc, data, keyring);
-  } else if (action == "padd") {
-    if (argc != 5) Usage(1);
-    std::string type = argv[2];
-    std::string desc = argv[3];
-    std::string keyring = argv[4];
-    return Padd(type, desc, keyring);
-  } else if (action == "restrict_keyring") {
-    if (argc != 3) Usage(1);
-    std::string keyring = argv[2];
-    return RestrictKeyring(keyring);
-  } else if (action == "unlink") {
-    if (argc != 4) Usage(1);
-    key_serial_t key = parseKeyOrDie(argv[2]);
-    const std::string keyring = argv[3];
-    return Unlink(key, keyring);
-  } else if (action == "security") {
-    if (argc != 3) Usage(1);
-    const char* key_str = argv[2];
-    key_serial_t key = parseKeyOrDie(key_str);
-    std::string context = RetrieveSecurityContext(key);
-    if (context.empty()) {
-      perror(key_str);
-      return 1;
-    }
-    fprintf(stderr, "%s\n", context.c_str());
-    return 0;
-  } else {
-    fprintf(stderr, "Unrecognized action: %s\n", action.c_str());
-    Usage(1);
-  }
-
-  return 0;
-}
diff --git a/libkeyutils/mini_keyctl/Android.bp b/libkeyutils/mini_keyctl/Android.bp
new file mode 100644
index 0000000..a04a3db
--- /dev/null
+++ b/libkeyutils/mini_keyctl/Android.bp
@@ -0,0 +1,27 @@
+cc_library_static {
+    name: "libmini_keyctl_static",
+    srcs: [
+        "mini_keyctl_utils.cpp"
+    ],
+    shared_libs: [
+        "libbase",
+        "libkeyutils",
+    ],
+    cflags: ["-Werror", "-Wall", "-Wextra"],
+    export_include_dirs: ["."],
+}
+
+cc_binary {
+    name: "mini-keyctl",
+    srcs: [
+        "mini_keyctl.cpp",
+    ],
+    static_libs: [
+        "libmini_keyctl_static",
+    ],
+    shared_libs: [
+        "libbase",
+        "libkeyutils",
+    ],
+    cflags: ["-Werror", "-Wall", "-Wextra"],
+}
diff --git a/libkeyutils/mini_keyctl/mini_keyctl.cpp b/libkeyutils/mini_keyctl/mini_keyctl.cpp
new file mode 100644
index 0000000..8aace9a
--- /dev/null
+++ b/libkeyutils/mini_keyctl/mini_keyctl.cpp
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+/*
+ * A tool loads keys to keyring.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <error.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <iterator>
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <keyutils.h>
+#include <mini_keyctl_utils.h>
+
+constexpr int kMaxCertSize = 4096;
+
+static void Usage(int exit_code) {
+  fprintf(stderr, "usage: mini-keyctl <action> [args,]\n");
+  fprintf(stderr, "       mini-keyctl add <type> <desc> <data> <keyring>\n");
+  fprintf(stderr, "       mini-keyctl padd <type> <desc> <keyring>\n");
+  fprintf(stderr, "       mini-keyctl unlink <key> <keyring>\n");
+  fprintf(stderr, "       mini-keyctl restrict_keyring <keyring>\n");
+  fprintf(stderr, "       mini-keyctl security <key>\n");
+  _exit(exit_code);
+}
+
+static key_serial_t parseKeyOrDie(const char* str) {
+  key_serial_t key;
+  if (!android::base::ParseInt(str, &key)) {
+    error(1 /* exit code */, 0 /* errno */, "Unparsable key: '%s'\n", str);
+  }
+  return key;
+}
+
+int Unlink(key_serial_t key, const std::string& keyring) {
+  key_serial_t keyring_id = android::GetKeyringId(keyring);
+  if (keyctl_unlink(key, keyring_id) < 0) {
+    error(1, errno, "Failed to unlink key %x from keyring %s", key, keyring.c_str());
+    return 1;
+  }
+  return 0;
+}
+
+int Add(const std::string& type, const std::string& desc, const std::string& data,
+        const std::string& keyring) {
+  if (data.size() > kMaxCertSize) {
+    error(1, 0, "Certificate too large");
+    return 1;
+  }
+
+  key_serial_t keyring_id = android::GetKeyringId(keyring);
+  key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id);
+
+  if (key < 0) {
+    error(1, errno, "Failed to add key");
+    return 1;
+  }
+
+  std::cout << key << std::endl;
+  return 0;
+}
+
+int Padd(const std::string& type, const std::string& desc, const std::string& keyring) {
+  key_serial_t keyring_id = android::GetKeyringId(keyring);
+
+  // read from stdin to get the certificates
+  std::istreambuf_iterator<char> begin(std::cin), end;
+  std::string data(begin, end);
+
+  if (data.size() > kMaxCertSize) {
+    error(1, 0, "Certificate too large");
+    return 1;
+  }
+
+  key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id);
+
+  if (key < 0) {
+    error(1, errno, "Failed to add key");
+    return 1;
+  }
+
+  std::cout << key << std::endl;
+  return 0;
+}
+
+int RestrictKeyring(const std::string& keyring) {
+  key_serial_t keyring_id = android::GetKeyringId(keyring);
+  if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) {
+    error(1, errno, "Cannot restrict keyring '%s'", keyring.c_str());
+    return 1;
+  }
+  return 0;
+}
+
+std::string RetrieveSecurityContext(key_serial_t key) {
+  // Simply assume this size is enough in practice.
+  const int kMaxSupportedSize = 256;
+  std::string context;
+  context.resize(kMaxSupportedSize);
+  long retval = keyctl_get_security(key, context.data(), kMaxSupportedSize);
+  if (retval < 0) {
+    error(1, errno, "Cannot get security context of key %x", key);
+    return std::string();
+  }
+  if (retval > kMaxSupportedSize) {
+    error(1, 0, "The key has unexpectedly long security context than %d", kMaxSupportedSize);
+    return std::string();
+  }
+  context.resize(retval);
+  return context;
+}
+
+int main(int argc, const char** argv) {
+  if (argc < 2) Usage(1);
+  const std::string action = argv[1];
+
+  if (action == "add") {
+    if (argc != 6) Usage(1);
+    std::string type = argv[2];
+    std::string desc = argv[3];
+    std::string data = argv[4];
+    std::string keyring = argv[5];
+    return Add(type, desc, data, keyring);
+  } else if (action == "padd") {
+    if (argc != 5) Usage(1);
+    std::string type = argv[2];
+    std::string desc = argv[3];
+    std::string keyring = argv[4];
+    return Padd(type, desc, keyring);
+  } else if (action == "restrict_keyring") {
+    if (argc != 3) Usage(1);
+    std::string keyring = argv[2];
+    return RestrictKeyring(keyring);
+  } else if (action == "unlink") {
+    if (argc != 4) Usage(1);
+    key_serial_t key = parseKeyOrDie(argv[2]);
+    const std::string keyring = argv[3];
+    return Unlink(key, keyring);
+  } else if (action == "security") {
+    if (argc != 3) Usage(1);
+    const char* key_str = argv[2];
+    key_serial_t key = parseKeyOrDie(key_str);
+    std::string context = RetrieveSecurityContext(key);
+    if (context.empty()) {
+      perror(key_str);
+      return 1;
+    }
+    fprintf(stderr, "%s\n", context.c_str());
+    return 0;
+  } else {
+    fprintf(stderr, "Unrecognized action: %s\n", action.c_str());
+    Usage(1);
+  }
+
+  return 0;
+}
diff --git a/libkeyutils/mini_keyctl/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl/mini_keyctl_utils.cpp
new file mode 100644
index 0000000..fb9503f
--- /dev/null
+++ b/libkeyutils/mini_keyctl/mini_keyctl_utils.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 <mini_keyctl_utils.h>
+
+#include <fstream>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+
+namespace android {
+
+namespace {
+
+std::vector<std::string> SplitBySpace(const std::string& s) {
+  std::istringstream iss(s);
+  return std::vector<std::string>{std::istream_iterator<std::string>{iss},
+                                  std::istream_iterator<std::string>{}};
+}
+
+}  // namespace
+
+// Find the keyring id. request_key(2) only finds keys in the process, session or thread keyring
+// hierarchy, but not internal keyring of a kernel subsystem (e.g. .fs-verity). To support all
+// cases, this function looks up a keyring's ID by parsing /proc/keys. The keyring description may
+// contain other information in the descritption section depending on the key type, only the first
+// word in the keyring description is used for searching.
+key_serial_t GetKeyringId(const std::string& keyring_desc) {
+  // If the keyring id is already a hex number, directly convert it to keyring id
+  key_serial_t keyring_id;
+  if (android::base::ParseInt(keyring_desc.c_str(), &keyring_id)) {
+    return keyring_id;
+  }
+
+  // Only keys allowed by SELinux rules will be shown here.
+  std::ifstream proc_keys_file("/proc/keys");
+  if (!proc_keys_file.is_open()) {
+    PLOG(ERROR) << "Failed to open /proc/keys";
+    return -1;
+  }
+
+  std::string line;
+  while (getline(proc_keys_file, line)) {
+    std::vector<std::string> tokens = SplitBySpace(line);
+    if (tokens.size() < 9) {
+      continue;
+    }
+    std::string key_id = "0x" + tokens[0];
+    std::string key_type = tokens[7];
+    // The key description may contain space.
+    std::string key_desc_prefix = tokens[8];
+    // The prefix has a ":" at the end
+    std::string key_desc_pattern = keyring_desc + ":";
+    if (key_type != "keyring" || key_desc_prefix != key_desc_pattern) {
+      continue;
+    }
+    if (!android::base::ParseInt(key_id.c_str(), &keyring_id)) {
+      LOG(ERROR) << "Unexpected key format in /proc/keys: " << key_id;
+      return -1;
+    }
+    return keyring_id;
+  }
+  return -1;
+}
+
+}  // namespace android
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/libkeyutils/mini_keyctl/mini_keyctl_utils.h
similarity index 68%
copy from libmeminfo/vts/vts_meminfo_test.cpp
copy to libkeyutils/mini_keyctl/mini_keyctl_utils.h
index 3193c31..cc31d29 100644
--- a/libmeminfo/vts/vts_meminfo_test.cpp
+++ b/libkeyutils/mini_keyctl/mini_keyctl_utils.h
@@ -14,18 +14,15 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
+#ifndef _MINI_KEYCTL_MINI_KEYCTL_UTILS_H_
+#define _MINI_KEYCTL_MINI_KEYCTL_UTILS_H_
 
-#include <meminfo/procmeminfo.h>
+#include <string>
+
+#include <keyutils.h>
 
 namespace android {
-namespace meminfo {
-
-// /proc/<pid>/smaps_rollup support is required.
-TEST(SmapsRollup, IsSupported) {
-    // Use init's pid for this test since it's the only known pid.
-    ASSERT_TRUE(IsSmapsRollupSupported(1));
-}
-
-}  // namespace meminfo
+key_serial_t GetKeyringId(const std::string& keyring_desc);
 }  // namespace android
+
+#endif  // _MINI_KEYCTL_MINI_KEYCTL_UTILS_H_
diff --git a/libkeyutils/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl_utils.cpp
deleted file mode 100644
index 56afea4..0000000
--- a/libkeyutils/mini_keyctl_utils.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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 <mini_keyctl_utils.h>
-
-#include <dirent.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <keyutils.h>
-
-static constexpr int kMaxCertSize = 4096;
-
-static std::vector<std::string> SplitBySpace(const std::string& s) {
-  std::istringstream iss(s);
-  return std::vector<std::string>{std::istream_iterator<std::string>{iss},
-                                  std::istream_iterator<std::string>{}};
-}
-
-// Find the keyring id. Because request_key(2) syscall is not available or the key is
-// kernel keyring, the id is looked up from /proc/keys. The keyring description may contain other
-// information in the descritption section depending on the key type, only the first word in the
-// keyring description is used for searching.
-static bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id) {
-  if (!keyring_id) {
-    LOG(ERROR) << "keyring_id is null";
-    return false;
-  }
-
-  // If the keyring id is already a hex number, directly convert it to keyring id
-  if (android::base::ParseInt(keyring_desc.c_str(), keyring_id)) {
-    return true;
-  }
-
-  // Only keys allowed by SELinux rules will be shown here.
-  std::ifstream proc_keys_file("/proc/keys");
-  if (!proc_keys_file.is_open()) {
-    PLOG(ERROR) << "Failed to open /proc/keys";
-    return false;
-  }
-
-  std::string line;
-  while (getline(proc_keys_file, line)) {
-    std::vector<std::string> tokens = SplitBySpace(line);
-    if (tokens.size() < 9) {
-      continue;
-    }
-    std::string key_id = tokens[0];
-    std::string key_type = tokens[7];
-    // The key description may contain space.
-    std::string key_desc_prefix = tokens[8];
-    // The prefix has a ":" at the end
-    std::string key_desc_pattern = keyring_desc + ":";
-    if (key_type != "keyring" || key_desc_prefix != key_desc_pattern) {
-      continue;
-    }
-    *keyring_id = std::stoi(key_id, nullptr, 16);
-    return true;
-  }
-  return false;
-}
-
-int Unlink(key_serial_t key, const std::string& keyring) {
-  key_serial_t keyring_id;
-  if (!GetKeyringId(keyring, &keyring_id)) {
-    LOG(ERROR) << "Can't find keyring " << keyring;
-    return 1;
-  }
-
-  if (keyctl_unlink(key, keyring_id) < 0) {
-    PLOG(ERROR) << "Failed to unlink key 0x" << std::hex << key << " from keyring " << keyring_id;
-    return 1;
-  }
-  return 0;
-}
-
-int Add(const std::string& type, const std::string& desc, const std::string& data,
-        const std::string& keyring) {
-  if (data.size() > kMaxCertSize) {
-    LOG(ERROR) << "Certificate too large";
-    return 1;
-  }
-
-  key_serial_t keyring_id;
-  if (!GetKeyringId(keyring, &keyring_id)) {
-    LOG(ERROR) << "Can not find keyring id";
-    return 1;
-  }
-
-  key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id);
-
-  if (key < 0) {
-    PLOG(ERROR) << "Failed to add key";
-    return 1;
-  }
-
-  LOG(INFO) << "Key " << desc << " added to " << keyring << " with key id: 0x" << std::hex << key;
-  return 0;
-}
-
-int Padd(const std::string& type, const std::string& desc, const std::string& keyring) {
-  key_serial_t keyring_id;
-  if (!GetKeyringId(keyring, &keyring_id)) {
-    LOG(ERROR) << "Can not find keyring id";
-    return 1;
-  }
-
-  // read from stdin to get the certificates
-  std::istreambuf_iterator<char> begin(std::cin), end;
-  std::string data(begin, end);
-
-  if (data.size() > kMaxCertSize) {
-    LOG(ERROR) << "Certificate too large";
-    return 1;
-  }
-
-  key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id);
-
-  if (key < 0) {
-    PLOG(ERROR) << "Failed to add key";
-    return 1;
-  }
-
-  LOG(INFO) << "Key " << desc << " added to " << keyring << " with key id: 0x" << std::hex << key;
-  return 0;
-}
-
-int RestrictKeyring(const std::string& keyring) {
-  key_serial_t keyring_id;
-  if (!GetKeyringId(keyring, &keyring_id)) {
-    LOG(ERROR) << "Cannot find keyring id";
-    return 1;
-  }
-
-  if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) {
-    PLOG(ERROR) << "Cannot restrict keyring " << keyring;
-    return 1;
-  }
-  return 0;
-}
-
-std::string RetrieveSecurityContext(key_serial_t key) {
-  // Simply assume this size is enough in practice.
-  const int kMaxSupportedSize = 256;
-  std::string context;
-  context.resize(kMaxSupportedSize);
-  long retval = keyctl_get_security(key, context.data(), kMaxSupportedSize);
-  if (retval < 0) {
-    PLOG(ERROR) << "Cannot get security context of key 0x" << std::hex << key;
-    return std::string();
-  }
-  if (retval > kMaxSupportedSize) {
-    LOG(ERROR) << "The key has unexpectedly long security context than " << kMaxSupportedSize;
-    return std::string();
-  }
-  context.resize(retval);
-  return context;
-}
diff --git a/libkeyutils/mini_keyctl_utils.h b/libkeyutils/mini_keyctl_utils.h
deleted file mode 100644
index 3616831..0000000
--- a/libkeyutils/mini_keyctl_utils.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 "include/keyutils.h"
-
-#include <string>
-
-// Add key to a keyring. Returns non-zero if error happens.
-int Add(const std::string& type, const std::string& desc, const std::string& data,
-        const std::string& keyring);
-
-// Add key from stdin to a keyring. Returns non-zero if error happens.
-int Padd(const std::string& type, const std::string& desc, const std::string& keyring);
-
-// Removes the link from a keyring to a key if exists. Return non-zero if error happens.
-int Unlink(key_serial_t key, const std::string& keyring);
-
-// Apply key-linking to a keyring. Return non-zero if error happens.
-int RestrictKeyring(const std::string& keyring);
-
-// Retrieves a key's security context. Return the context string, or empty string on error.
-std::string RetrieveSecurityContext(key_serial_t key);
diff --git a/liblog/Android.bp b/liblog/Android.bp
index da475cb..bab57c0 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -15,20 +15,15 @@
 //
 
 liblog_sources = [
-    "config_read.cpp",
-    "config_write.cpp",
     "log_event_list.cpp",
     "log_event_write.cpp",
-    "logger_lock.cpp",
     "logger_name.cpp",
     "logger_read.cpp",
     "logger_write.cpp",
     "logprint.cpp",
-    "stderr_write.cpp",
 ]
 liblog_host_sources = [
     "fake_log_device.cpp",
-    "fake_writer.cpp",
 ]
 liblog_target_sources = [
     "event_tag_map.cpp",
@@ -45,6 +40,7 @@
     host_supported: true,
     vendor_available: true,
     recovery_available: true,
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
     system_shared_libs: [],
     stl: "none",
@@ -67,6 +63,7 @@
     name: "liblog",
     host_supported: true,
     recovery_available: true,
+    native_bridge_supported: true,
     srcs: liblog_sources,
 
     target: {
@@ -98,7 +95,10 @@
         },
     },
 
-    header_libs: ["liblog_headers"],
+    header_libs: [
+        "libbase_headers",
+        "liblog_headers",
+    ],
     export_header_lib_headers: ["liblog_headers"],
 
     stubs: {
@@ -106,8 +106,15 @@
         versions: ["10000"],
     },
 
+    // TODO(tomcherry): Renable this before release branch is cut
+    header_abi_checker: {
+        enabled: false,
+    },
+
     cflags: [
+        "-Wall",
         "-Werror",
+        "-Wextra",
         // This is what we want to do:
         //  liblog_cflags := $(shell \
         //   sed -n \
@@ -138,6 +145,7 @@
 
 llndk_library {
     name: "liblog",
+    native_bridge_supported: true,
     symbol_file: "liblog.map.txt",
     export_include_dirs: ["include_vndk"],
 }
diff --git a/liblog/README.md b/liblog/README.md
index 98bee9f..871399a 100644
--- a/liblog/README.md
+++ b/liblog/README.md
@@ -96,11 +96,6 @@
 
     int android_log_destroy(android_log_context *ctx)
 
-    #include <log/log_transport.h>
-
-    int android_set_log_transport(int transport_flag)
-    int android_get_log_transport()
-
 Description
 -----------
 
@@ -144,11 +139,6 @@
 that was used when opening the sub-log.  It is recommended to open the log `ANDROID_LOG_RDONLY` in
 these cases.
 
-`android_set_log_transport()` selects transport filters.  Argument is either `LOGGER_DEFAULT`,
-`LOGGER_LOGD`, or `LOGGER_NULL`. Log to logger daemon for default or logd, or drop contents on floor
-respectively.  `Both android_set_log_transport()` and `android_get_log_transport()` return the
-current transport mask, or a negative errno for any problems.
-
 Errors
 ------
 
diff --git a/liblog/README.protocol.md b/liblog/README.protocol.md
new file mode 100644
index 0000000..fef29c9
--- /dev/null
+++ b/liblog/README.protocol.md
@@ -0,0 +1,49 @@
+# liblog -> logd
+
+The data that liblog sends to logd is represented below.
+
+    struct {
+        android_log_header_t header;
+        union {
+           struct {
+                char     prio;
+                char     tag[...];
+                char     message[...];
+            } string;
+            struct {
+                android_event_header_t event_header;
+                android_event_*_t      payload[...];
+            } binary;
+        };
+    };
+
+The payload, excluding the header, has a max size of LOGGER_ENTRY_MAX_PAYLOAD.
+
+## header
+
+The header is added immediately before sending the log message to logd.
+
+## `string` payload
+
+The `string` part of the union is for normal buffers (main, system, radio, etc) and consists of a
+single character priority, followed by a variable length null terminated string for the tag, and
+finally a variable length null terminated string for the message.
+
+This payload is used for the `__android_log_buf_write()` family of functions.
+
+## `binary` payload
+
+The `binary` part of the union is for binary buffers (events, security, etc) and consists of an
+android_event_header_t struct followed by a variable number of android_event_*_t
+(android_event_list_t, android_event_int_t, etc) structs.
+
+If multiple android_event_*_t elements are present, then they must be in a list and the first
+element in payload must be an android_event_list_t.
+
+This payload is used for the `__android_log_bwrite()` family of functions. It is additionally used
+for `android_log_write_list()` and the related functions that manipulate event lists.
+
+# logd -> liblog
+
+logd sends a `logger_entry` struct to liblog followed by the payload. The payload is identical to
+the payloads defined above. The max size of the entire message from logd is LOGGER_ENTRY_MAX_LEN.
diff --git a/liblog/config_read.cpp b/liblog/config_read.cpp
deleted file mode 100644
index 3139f78..0000000
--- a/liblog/config_read.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2016 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 <log/log_transport.h>
-
-#include "config_read.h"
-#include "logger.h"
-
-struct listnode __android_log_transport_read = {&__android_log_transport_read,
-                                                &__android_log_transport_read};
-struct listnode __android_log_persist_read = {&__android_log_persist_read,
-                                              &__android_log_persist_read};
-
-static void __android_log_add_transport(struct listnode* list,
-                                        struct android_log_transport_read* transport) {
-  uint32_t i;
-
-  /* Try to keep one functioning transport for each log buffer id */
-  for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) {
-    struct android_log_transport_read* transp;
-
-    if (list_empty(list)) {
-      if (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0)) {
-        list_add_tail(list, &transport->node);
-        return;
-      }
-    } else {
-      read_transport_for_each(transp, list) {
-        if (!transp->available) {
-          return;
-        }
-        if (((*transp->available)(static_cast<log_id_t>(i)) < 0) &&
-            (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0))) {
-          list_add_tail(list, &transport->node);
-          return;
-        }
-      }
-    }
-  }
-}
-
-void __android_log_config_read() {
-#if (FAKE_LOG_DEVICE == 0)
-  if ((__android_log_transport == LOGGER_DEFAULT) || (__android_log_transport & LOGGER_LOGD)) {
-    extern struct android_log_transport_read logdLoggerRead;
-    extern struct android_log_transport_read pmsgLoggerRead;
-
-    __android_log_add_transport(&__android_log_transport_read, &logdLoggerRead);
-    __android_log_add_transport(&__android_log_persist_read, &pmsgLoggerRead);
-  }
-#endif
-}
-
-void __android_log_config_read_close() {
-  struct android_log_transport_read* transport;
-  struct listnode* n;
-
-  read_transport_for_each_safe(transport, n, &__android_log_transport_read) {
-    list_remove(&transport->node);
-  }
-  read_transport_for_each_safe(transport, n, &__android_log_persist_read) {
-    list_remove(&transport->node);
-  }
-}
diff --git a/liblog/config_read.h b/liblog/config_read.h
deleted file mode 100644
index 212b8a0..0000000
--- a/liblog/config_read.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2016 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 <cutils/list.h>
-
-#include "log_portability.h"
-
-__BEGIN_DECLS
-
-extern struct listnode __android_log_transport_read;
-extern struct listnode __android_log_persist_read;
-
-#define read_transport_for_each(transp, transports)                           \
-  for ((transp) = node_to_item((transports)->next,                            \
-                               struct android_log_transport_read, node);      \
-       ((transp) != node_to_item((transports),                                \
-                                 struct android_log_transport_read, node)) && \
-       ((transp) != node_to_item((transp)->node.next,                         \
-                                 struct android_log_transport_read, node));   \
-       (transp) = node_to_item((transp)->node.next,                           \
-                               struct android_log_transport_read, node))
-
-#define read_transport_for_each_safe(transp, n, transports)                   \
-  for ((transp) = node_to_item((transports)->next,                            \
-                               struct android_log_transport_read, node),      \
-      (n) = (transp)->node.next;                                              \
-       ((transp) != node_to_item((transports),                                \
-                                 struct android_log_transport_read, node)) && \
-       ((transp) !=                                                           \
-        node_to_item((n), struct android_log_transport_read, node));          \
-       (transp) = node_to_item((n), struct android_log_transport_read, node), \
-      (n) = (transp)->node.next)
-
-void __android_log_config_read();
-void __android_log_config_read_close();
-
-__END_DECLS
diff --git a/liblog/config_write.cpp b/liblog/config_write.cpp
deleted file mode 100644
index d454379..0000000
--- a/liblog/config_write.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2016 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 <log/log_transport.h>
-
-#include "config_write.h"
-#include "logger.h"
-
-struct listnode __android_log_transport_write = {&__android_log_transport_write,
-                                                 &__android_log_transport_write};
-struct listnode __android_log_persist_write = {&__android_log_persist_write,
-                                               &__android_log_persist_write};
-
-static void __android_log_add_transport(struct listnode* list,
-                                        struct android_log_transport_write* transport) {
-  uint32_t i;
-
-  /* Try to keep one functioning transport for each log buffer id */
-  for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) {
-    struct android_log_transport_write* transp;
-
-    if (list_empty(list)) {
-      if (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0)) {
-        list_add_tail(list, &transport->node);
-        return;
-      }
-    } else {
-      write_transport_for_each(transp, list) {
-        if (!transp->available) {
-          return;
-        }
-        if (((*transp->available)(static_cast<log_id_t>(i)) < 0) &&
-            (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0))) {
-          list_add_tail(list, &transport->node);
-          return;
-        }
-      }
-    }
-  }
-}
-
-void __android_log_config_write() {
-  if ((__android_log_transport == LOGGER_DEFAULT) || (__android_log_transport & LOGGER_LOGD)) {
-#if (FAKE_LOG_DEVICE == 0)
-    extern struct android_log_transport_write logdLoggerWrite;
-    extern struct android_log_transport_write pmsgLoggerWrite;
-
-    __android_log_add_transport(&__android_log_transport_write, &logdLoggerWrite);
-    __android_log_add_transport(&__android_log_persist_write, &pmsgLoggerWrite);
-#else
-    extern struct android_log_transport_write fakeLoggerWrite;
-
-    __android_log_add_transport(&__android_log_transport_write, &fakeLoggerWrite);
-#endif
-  }
-
-  if (__android_log_transport & LOGGER_STDERR) {
-    extern struct android_log_transport_write stderrLoggerWrite;
-
-    /*
-     * stderr logger should be primary if we can be the only one, or if
-     * already in the primary list.  Otherwise land in the persist list.
-     * Remember we can be called here if we are already initialized.
-     */
-    if (list_empty(&__android_log_transport_write)) {
-      __android_log_add_transport(&__android_log_transport_write, &stderrLoggerWrite);
-    } else {
-      struct android_log_transport_write* transp;
-      write_transport_for_each(transp, &__android_log_transport_write) {
-        if (transp == &stderrLoggerWrite) {
-          return;
-        }
-      }
-      __android_log_add_transport(&__android_log_persist_write, &stderrLoggerWrite);
-    }
-  }
-}
-
-void __android_log_config_write_close() {
-  struct android_log_transport_write* transport;
-  struct listnode* n;
-
-  write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
-    transport->logMask = 0;
-    list_remove(&transport->node);
-  }
-  write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
-    transport->logMask = 0;
-    list_remove(&transport->node);
-  }
-}
diff --git a/liblog/config_write.h b/liblog/config_write.h
deleted file mode 100644
index a901f13..0000000
--- a/liblog/config_write.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2016 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 <cutils/list.h>
-
-#include "log_portability.h"
-
-__BEGIN_DECLS
-
-extern struct listnode __android_log_transport_write;
-extern struct listnode __android_log_persist_write;
-
-#define write_transport_for_each(transp, transports)                           \
-  for ((transp) = node_to_item((transports)->next,                             \
-                               struct android_log_transport_write, node);      \
-       ((transp) != node_to_item((transports),                                 \
-                                 struct android_log_transport_write, node)) && \
-       ((transp) != node_to_item((transp)->node.next,                          \
-                                 struct android_log_transport_write, node));   \
-       (transp) = node_to_item((transp)->node.next,                            \
-                               struct android_log_transport_write, node))
-
-#define write_transport_for_each_safe(transp, n, transports)                   \
-  for ((transp) = node_to_item((transports)->next,                             \
-                               struct android_log_transport_write, node),      \
-      (n) = (transp)->node.next;                                               \
-       ((transp) != node_to_item((transports),                                 \
-                                 struct android_log_transport_write, node)) && \
-       ((transp) !=                                                            \
-        node_to_item((n), struct android_log_transport_write, node));          \
-       (transp) = node_to_item((n), struct android_log_transport_write, node), \
-      (n) = (transp)->node.next)
-
-void __android_log_config_write();
-void __android_log_config_write_close();
-
-__END_DECLS
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 22cf43b..2886289 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -494,7 +494,7 @@
 
 // Cache miss, go to logd to acquire a public reference.
 // Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map?
-static const TagFmt* __getEventTag(EventTagMap* map, unsigned int tag) {
+static const TagFmt* __getEventTag([[maybe_unused]] EventTagMap* map, unsigned int tag) {
   // call event tag service to arrange for a new tag
   char* buf = NULL;
   // Can not use android::base::StringPrintf, asprintf + free instead.
@@ -515,8 +515,9 @@
     } else {
       size = ret;
     }
+#ifdef __ANDROID__
     // Ask event log tag service for an existing entry
-    if (__send_log_msg(buf, size) >= 0) {
+    if (SendLogdControlMessage(buf, size) >= 0) {
       buf[size - 1] = '\0';
       char* ep;
       unsigned long val = strtoul(buf, &ep, 10);  // return size
@@ -529,6 +530,7 @@
         }
       }
     }
+#endif
     free(buf);
   }
   return NULL;
@@ -618,8 +620,9 @@
     } else {
       size = ret;
     }
+#ifdef __ANDROID__
     // Ask event log tag service for an allocation
-    if (__send_log_msg(buf, size) >= 0) {
+    if (SendLogdControlMessage(buf, size) >= 0) {
       buf[size - 1] = '\0';
       unsigned long val = strtoul(buf, &cp, 10);        // return size
       if ((buf != cp) && (val > 0) && (*cp == '\n')) {  // truncation OK
@@ -635,6 +638,7 @@
         }
       }
     }
+#endif
     free(buf);
   }
 
diff --git a/liblog/fake_log_device.cpp b/liblog/fake_log_device.cpp
index 428a482..2ec6393 100644
--- a/liblog/fake_log_device.cpp
+++ b/liblog/fake_log_device.cpp
@@ -23,18 +23,21 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#if !defined(_WIN32)
-#include <pthread.h>
-#endif
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 
+#include <mutex>
+
+#include <android-base/no_destructor.h>
 #include <android/log.h>
+#include <log/log_id.h>
+#include <log/logprint.h>
 
 #include "log_portability.h"
+#include "logger.h"
 
 #define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */
 
@@ -46,37 +49,21 @@
 #define TRACE(...) ((void)0)
 #endif
 
-/* from the long-dead utils/Log.cpp */
-typedef enum {
-  FORMAT_OFF = 0,
-  FORMAT_BRIEF,
-  FORMAT_PROCESS,
-  FORMAT_TAG,
-  FORMAT_THREAD,
-  FORMAT_RAW,
-  FORMAT_TIME,
-  FORMAT_THREADTIME,
-  FORMAT_LONG
-} LogFormat;
+static void FakeClose();
+static int FakeWrite(log_id_t log_id, struct timespec* ts, struct iovec* vec, size_t nr);
 
-/*
- * Log driver state.
- */
+struct android_log_transport_write fakeLoggerWrite = {
+    .close = FakeClose,
+    .write = FakeWrite,
+};
+
 typedef struct LogState {
-  /* the fake fd that's seen by the user */
-  int fakeFd;
-
-  /* a printable name for this fake device */
-  char debugName[sizeof("/dev/log/security")];
-
-  /* nonzero if this is a binary log */
-  int isBinary;
-
+  bool initialized = false;
   /* global minimum priority */
-  int globalMinPriority;
+  int global_min_priority;
 
   /* output format */
-  LogFormat outputFormat;
+  AndroidLogPrintFormat output_format;
 
   /* tags and priorities */
   struct {
@@ -85,82 +72,8 @@
   } tagSet[kTagSetSize];
 } LogState;
 
-#if !defined(_WIN32)
-/*
- * Locking.  Since we're emulating a device, we need to be prepared
- * to have multiple callers at the same time.  This lock is used
- * to both protect the fd list and to prevent LogStates from being
- * freed out from under a user.
- */
-static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;
-
-static void lock() {
-  /*
-   * If we trigger a signal handler in the middle of locked activity and the
-   * signal handler logs a message, we could get into a deadlock state.
-   */
-  pthread_mutex_lock(&fakeLogDeviceLock);
-}
-
-static void unlock() {
-  pthread_mutex_unlock(&fakeLogDeviceLock);
-}
-
-#else  // !defined(_WIN32)
-
-#define lock() ((void)0)
-#define unlock() ((void)0)
-
-#endif  // !defined(_WIN32)
-
-/*
- * File descriptor management.
- */
-#define FAKE_FD_BASE 10000
-#define MAX_OPEN_LOGS 8
-static LogState openLogTable[MAX_OPEN_LOGS];
-
-/*
- * Allocate an fd and associate a new LogState with it.
- * The fd is available via the fakeFd field of the return value.
- */
-static LogState* createLogState() {
-  size_t i;
-
-  for (i = 0; i < (sizeof(openLogTable) / sizeof(openLogTable[0])); i++) {
-    if (openLogTable[i].fakeFd == 0) {
-      openLogTable[i].fakeFd = FAKE_FD_BASE + i;
-      return &openLogTable[i];
-    }
-  }
-  return NULL;
-}
-
-/*
- * Translate an fd to a LogState.
- */
-static LogState* fdToLogState(int fd) {
-  if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) {
-    return &openLogTable[fd - FAKE_FD_BASE];
-  }
-  return NULL;
-}
-
-/*
- * Unregister the fake fd and free the memory it pointed to.
- */
-static void deleteFakeFd(int fd) {
-  LogState* ls;
-
-  lock();
-
-  ls = fdToLogState(fd);
-  if (ls != NULL) {
-    memset(&openLogTable[fd - FAKE_FD_BASE], 0, sizeof(openLogTable[0]));
-  }
-
-  unlock();
-}
+static LogState log_state;
+static android::base::NoDestructor<std::mutex> fake_log_mutex;
 
 /*
  * Configure logging based on ANDROID_LOG_TAGS environment variable.  We
@@ -175,19 +88,11 @@
  * We also want to check ANDROID_PRINTF_LOG to determine how the output
  * will look.
  */
-static void configureInitialState(const char* pathName, LogState* logState) {
-  static const int kDevLogLen = sizeof("/dev/log/") - 1;
-
-  strncpy(logState->debugName, pathName, sizeof(logState->debugName));
-  logState->debugName[sizeof(logState->debugName) - 1] = '\0';
-
-  /* identify binary logs */
-  if (!strcmp(pathName + kDevLogLen, "events") || !strcmp(pathName + kDevLogLen, "security")) {
-    logState->isBinary = 1;
-  }
+void InitializeLogStateLocked() {
+  log_state.initialized = true;
 
   /* global min priority defaults to "info" level */
-  logState->globalMinPriority = ANDROID_LOG_INFO;
+  log_state.global_min_priority = ANDROID_LOG_INFO;
 
   /*
    * This is based on the the long-dead utils/Log.cpp code.
@@ -265,11 +170,11 @@
       }
 
       if (tagName[0] == 0) {
-        logState->globalMinPriority = minPrio;
+        log_state.global_min_priority = minPrio;
         TRACE("+++ global min prio %d\n", logState->globalMinPriority);
       } else {
-        logState->tagSet[entry].minPriority = minPrio;
-        strcpy(logState->tagSet[entry].tag, tagName);
+        log_state.tagSet[entry].minPriority = minPrio;
+        strcpy(log_state.tagSet[entry].tag, tagName);
         TRACE("+++ entry %d: %s:%d\n", entry, logState->tagSet[entry].tag,
               logState->tagSet[entry].minPriority);
         entry++;
@@ -281,7 +186,7 @@
    * Taken from the long-dead utils/Log.cpp
    */
   const char* fstr = getenv("ANDROID_PRINTF_LOG");
-  LogFormat format;
+  AndroidLogPrintFormat format;
   if (fstr == NULL) {
     format = FORMAT_BRIEF;
   } else {
@@ -300,10 +205,10 @@
     else if (strcmp(fstr, "long") == 0)
       format = FORMAT_PROCESS;
     else
-      format = (LogFormat)atoi(fstr);  // really?!
+      format = (AndroidLogPrintFormat)atoi(fstr);  // really?!
   }
 
-  logState->outputFormat = format;
+  log_state.output_format = format;
 }
 
 /*
@@ -348,7 +253,7 @@
  *
  * Log format parsing taken from the long-dead utils/Log.cpp.
  */
-static void showLog(LogState* state, int logPrio, const char* tag, const char* msg) {
+static void ShowLog(int logPrio, const char* tag, const char* msg) {
 #if !defined(_WIN32)
   struct tm tmBuf;
 #endif
@@ -391,7 +296,7 @@
    */
   size_t prefixLen, suffixLen;
 
-  switch (state->outputFormat) {
+  switch (log_state.output_format) {
     case FORMAT_TAG:
       prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag);
       strcpy(suffixBuf, "\n");
@@ -548,35 +453,28 @@
  *  tag (N bytes -- null-terminated ASCII string)
  *  message (N bytes -- null-terminated ASCII string)
  */
-ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count) {
-  LogState* state;
-
+static int FakeWrite(log_id_t log_id, struct timespec*, struct iovec* vector, size_t count) {
   /* Make sure that no-one frees the LogState while we're using it.
    * Also guarantees that only one thread is in showLog() at a given
    * time (if it matters).
    */
-  lock();
+  auto lock = std::lock_guard{*fake_log_mutex};
 
-  state = fdToLogState(fd);
-  if (state == NULL) {
-    errno = EBADF;
-    unlock();
-    return -1;
+  if (!log_state.initialized) {
+    InitializeLogStateLocked();
   }
 
-  if (state->isBinary) {
-    TRACE("%s: ignoring binary log\n", state->debugName);
-    unlock();
+  if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS || log_id == LOG_ID_SECURITY) {
+    TRACE("%s: ignoring binary log\n", android_log_id_to_name(log_id));
     int len = 0;
-    for (int i = 0; i < count; ++i) {
+    for (size_t i = 0; i < count; ++i) {
       len += vector[i].iov_len;
     }
     return len;
   }
 
   if (count != 3) {
-    TRACE("%s: writevLog with count=%d not expected\n", state->debugName, count);
-    unlock();
+    TRACE("%s: writevLog with count=%d not expected\n", android_log_id_to_name(log_id), count);
     return -1;
   }
 
@@ -586,32 +484,30 @@
   const char* msg = (const char*)vector[2].iov_base;
 
   /* see if this log tag is configured */
-  int i;
-  int minPrio = state->globalMinPriority;
-  for (i = 0; i < kTagSetSize; i++) {
-    if (state->tagSet[i].minPriority == ANDROID_LOG_UNKNOWN)
+  int minPrio = log_state.global_min_priority;
+  for (size_t i = 0; i < kTagSetSize; i++) {
+    if (log_state.tagSet[i].minPriority == ANDROID_LOG_UNKNOWN)
       break; /* reached end of configured values */
 
-    if (strcmp(state->tagSet[i].tag, tag) == 0) {
-      minPrio = state->tagSet[i].minPriority;
+    if (strcmp(log_state.tagSet[i].tag, tag) == 0) {
+      minPrio = log_state.tagSet[i].minPriority;
       break;
     }
   }
 
   if (logPrio >= minPrio) {
-    showLog(state, logPrio, tag, msg);
+    ShowLog(logPrio, tag, msg);
   }
 
-  unlock();
   int len = 0;
-  for (i = 0; i < count; ++i) {
+  for (size_t i = 0; i < count; ++i) {
     len += vector[i].iov_len;
   }
   return len;
 }
 
 /*
- * Free up our state and close the fake descriptor.
+ * Reset out state.
  *
  * The logger API has no means or need to 'stop' or 'close' using the logs,
  * and as such, there is no way for that 'stop' or 'close' to translate into
@@ -623,35 +519,10 @@
  * call is in the exit handler. Logging can continue in the exit handler to
  * help debug HOST tools ...
  */
-int fakeLogClose(int fd) {
-  deleteFakeFd(fd);
-  return 0;
-}
+static void FakeClose() {
+  auto lock = std::lock_guard{*fake_log_mutex};
 
-/*
- * Open a log output device and return a fake fd.
- */
-int fakeLogOpen(const char* pathName) {
-  LogState* logState;
-  int fd = -1;
-
-  lock();
-
-  logState = createLogState();
-  if (logState != NULL) {
-    configureInitialState(pathName, logState);
-    fd = logState->fakeFd;
-  } else {
-    errno = ENFILE;
-  }
-
-  unlock();
-
-  return fd;
-}
-
-ssize_t __send_log_msg(char*, size_t) {
-  return -ENODEV;
+  memset(&log_state, 0, sizeof(log_state));
 }
 
 int __android_log_is_loggable(int prio, const char*, int def) {
diff --git a/liblog/fake_log_device.h b/liblog/fake_log_device.h
index ce54db2..bd2256c 100644
--- a/liblog/fake_log_device.h
+++ b/liblog/fake_log_device.h
@@ -29,7 +29,6 @@
 int fakeLogClose(int fd);
 ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count);
 
-ssize_t __send_log_msg(char*, size_t);
 int __android_log_is_loggable(int prio, const char*, int def);
 int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
 int __android_log_is_debuggable();
diff --git a/liblog/fake_writer.cpp b/liblog/fake_writer.cpp
deleted file mode 100644
index c0b0e69..0000000
--- a/liblog/fake_writer.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2007-2016 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 <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <log/log.h>
-
-#include "config_write.h"
-#include "fake_log_device.h"
-#include "log_portability.h"
-#include "logger.h"
-
-static int fakeOpen();
-static void fakeClose();
-static int fakeWrite(log_id_t log_id, struct timespec* ts, struct iovec* vec, size_t nr);
-
-static int logFds[(int)LOG_ID_MAX] = {-1, -1, -1, -1, -1, -1};
-
-struct android_log_transport_write fakeLoggerWrite = {
-    .node = {&fakeLoggerWrite.node, &fakeLoggerWrite.node},
-    .context.priv = &logFds,
-    .name = "fake",
-    .available = NULL,
-    .open = fakeOpen,
-    .close = fakeClose,
-    .write = fakeWrite,
-};
-
-static int fakeOpen() {
-  int i;
-
-  for (i = 0; i < LOG_ID_MAX; i++) {
-    /*
-     * Known maximum size string, plus an 8 character margin to deal with
-     * possible independent changes to android_log_id_to_name().
-     */
-    char buf[sizeof("/dev/log_security") + 8];
-    if (logFds[i] >= 0) {
-      continue;
-    }
-    snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(static_cast<log_id_t>(i)));
-    logFds[i] = fakeLogOpen(buf);
-    if (logFds[i] < 0) {
-      fprintf(stderr, "fakeLogOpen(%s) failed\n", buf);
-    }
-  }
-  return 0;
-}
-
-static void fakeClose() {
-  int i;
-
-  for (i = 0; i < LOG_ID_MAX; i++) {
-    fakeLogClose(logFds[i]);
-    logFds[i] = -1;
-  }
-}
-
-static int fakeWrite(log_id_t log_id, struct timespec*, struct iovec* vec, size_t nr) {
-  ssize_t ret;
-  size_t i;
-  int logFd, len;
-
-  if (/*(int)log_id >= 0 &&*/ (int)log_id >= (int)LOG_ID_MAX) {
-    return -EINVAL;
-  }
-
-  len = 0;
-  for (i = 0; i < nr; ++i) {
-    len += vec[i].iov_len;
-  }
-
-  if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
-    len = LOGGER_ENTRY_MAX_PAYLOAD;
-  }
-
-  logFd = logFds[(int)log_id];
-  ret = TEMP_FAILURE_RETRY(fakeLogWritev(logFd, vec, nr));
-  if (ret < 0) {
-    ret = -errno;
-  } else if (ret > len) {
-    ret = len;
-  }
-
-  return ret;
-}
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index b2f0ed9..7290789 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -96,20 +96,14 @@
  * [printf(3)](http://man7.org/linux/man-pages/man3/printf.3.html).
  */
 int __android_log_print(int prio, const char* tag, const char* fmt, ...)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 3, 4)))
-#endif
-    ;
+    __attribute__((__format__(printf, 3, 4)));
 
 /**
  * Equivalent to `__android_log_print`, but taking a `va_list`.
  * (If `__android_log_print` is like `printf`, this is like `vprintf`.)
  */
 int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 3, 0)))
-#endif
-    ;
+    __attribute__((__format__(printf, 3, 0)));
 
 /**
  * Writes an assertion failure to the log (as `ANDROID_LOG_FATAL`) and to
@@ -122,20 +116,14 @@
  *
  * Most callers should use
  * [assert(3)](http://man7.org/linux/man-pages/man3/assert.3.html) from
- * `<assert.h>` instead, or the `__assert` and `__assert2` functions provided by
- * bionic if more control is needed. They support automatically including the
- * source filename and line number more conveniently than this function.
+ * `&lt;assert.h&gt;` instead, or the `__assert` and `__assert2` functions
+ * provided by bionic if more control is needed. They support automatically
+ * including the source filename and line number more conveniently than this
+ * function.
  */
-void __android_log_assert(const char* cond, const char* tag, const char* fmt,
-                          ...)
-#if defined(__GNUC__)
-    __attribute__((__noreturn__))
-    __attribute__((__format__(printf, 3, 4)))
-#endif
-    ;
+void __android_log_assert(const char* cond, const char* tag, const char* fmt, ...)
+    __attribute__((__noreturn__)) __attribute__((__format__(printf, 3, 4)));
 
-#ifndef log_id_t_defined
-#define log_id_t_defined
 /**
  * Identifies a specific log buffer for __android_log_buf_write()
  * and __android_log_buf_print().
@@ -162,7 +150,6 @@
 
   LOG_ID_MAX
 } log_id_t;
-#endif
 
 /**
  * Writes the constant string `text` to the log buffer `id`,
@@ -170,8 +157,7 @@
  *
  * Apps should use __android_log_write() instead.
  */
-int __android_log_buf_write(int bufID, int prio, const char* tag,
-                            const char* text);
+int __android_log_buf_write(int bufID, int prio, const char* tag, const char* text);
 
 /**
  * Writes a formatted string to log buffer `id`,
@@ -181,12 +167,8 @@
  *
  * Apps should use __android_log_print() instead.
  */
-int __android_log_buf_print(int bufID, int prio, const char* tag,
-                            const char* fmt, ...)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 4, 5)))
-#endif
-    ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+    __attribute__((__format__(printf, 4, 5)));
 
 #ifdef __cplusplus
 }
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 2687b3a..f7ec208 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <stddef.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 5928649..90d1e76 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -22,7 +22,6 @@
 #endif
 #include <stdint.h> /* uint16_t, int32_t */
 #include <stdio.h>
-#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -65,21 +64,6 @@
 #endif
 #endif
 
-/* --------------------------------------------------------------------- */
-
-/*
- * This file uses ", ## __VA_ARGS__" zero-argument token pasting to
- * work around issues with debug-only syntax errors in assertions
- * that are missing format strings.  See commit
- * 19299904343daf191267564fe32e6cd5c165cd42
- */
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#endif
-
-/* --------------------------------------------------------------------- */
-
 /*
  * Event logging.
  */
@@ -164,10 +148,6 @@
  */
 void __android_log_close(void);
 
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 636d417..deadf20 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -36,16 +36,11 @@
 /*
  * The opaque context used to manipulate lists of events.
  */
-#ifndef __android_log_context_defined
-#define __android_log_context_defined
 typedef struct android_log_context_internal* android_log_context;
-#endif
 
 /*
  * Elements returned when reading a list of events.
  */
-#ifndef __android_log_list_element_defined
-#define __android_log_list_element_defined
 typedef struct {
   AndroidEventLogType type;
   uint16_t complete;
@@ -57,7 +52,6 @@
     float float32;
   } data;
 } android_log_list_element;
-#endif
 
 /*
  * Creates a context associated with an event tag to write elements to
@@ -104,8 +98,6 @@
 int android_log_destroy(android_log_context* ctx);
 
 #ifdef __cplusplus
-#ifndef __class_android_log_event_list_defined
-#define __class_android_log_event_list_defined
 /* android_log_list C++ helpers */
 extern "C++" {
 class android_log_event_list {
@@ -280,7 +272,6 @@
 };
 }
 #endif
-#endif
 
 #ifdef __cplusplus
 }
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index c052a50..c8fafe7 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -16,41 +16,19 @@
 
 #pragma once
 
+#include <android/log.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifndef log_id_t_defined
-#define log_id_t_defined
-typedef enum log_id {
-  LOG_ID_MIN = 0,
-
-  LOG_ID_MAIN = 0,
-  LOG_ID_RADIO = 1,
-  LOG_ID_EVENTS = 2,
-  LOG_ID_SYSTEM = 3,
-  LOG_ID_CRASH = 4,
-  LOG_ID_STATS = 5,
-  LOG_ID_SECURITY = 6,
-  LOG_ID_KERNEL = 7, /* place last, third-parties can not use it */
-
-  LOG_ID_MAX
-} log_id_t;
-#endif
-#define sizeof_log_id_t sizeof(typeof_log_id_t)
-#define typeof_log_id_t unsigned char
-
 /*
  * Send a simple string to the log.
  */
 int __android_log_buf_write(int bufID, int prio, const char* tag,
                             const char* text);
-int __android_log_buf_print(int bufID, int prio, const char* tag,
-                            const char* fmt, ...)
-#if defined(__GNUC__)
-    __attribute__((__format__(printf, 4, 5)))
-#endif
-    ;
+int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt, ...)
+    __attribute__((__format__(printf, 4, 5)));
 
 /*
  * log_id_t helpers
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index fdef306..18c1c33 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -50,64 +50,9 @@
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wzero-length-array"
-/*
- * The userspace structure for version 1 of the logger_entry ABI.
- */
-#ifndef __struct_logger_entry_defined
-#define __struct_logger_entry_defined
 struct logger_entry {
-  uint16_t len;   /* length of the payload */
-  uint16_t __pad; /* no matter what, we get 2 bytes of padding */
-  int32_t pid;    /* generating process's pid */
-  int32_t tid;    /* generating process's tid */
-  int32_t sec;    /* seconds since Epoch */
-  int32_t nsec;   /* nanoseconds */
-  char msg[0]; /* the entry's payload */
-};
-#endif
-
-/*
- * The userspace structure for version 2 of the logger_entry ABI.
- */
-#ifndef __struct_logger_entry_v2_defined
-#define __struct_logger_entry_v2_defined
-struct logger_entry_v2 {
   uint16_t len;      /* length of the payload */
-  uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
-  int32_t pid;       /* generating process's pid */
-  int32_t tid;       /* generating process's tid */
-  int32_t sec;       /* seconds since Epoch */
-  int32_t nsec;      /* nanoseconds */
-  uint32_t euid;     /* effective UID of logger */
-  char msg[0]; /* the entry's payload */
-} __attribute__((__packed__));
-#endif
-
-/*
- * The userspace structure for version 3 of the logger_entry ABI.
- */
-#ifndef __struct_logger_entry_v3_defined
-#define __struct_logger_entry_v3_defined
-struct logger_entry_v3 {
-  uint16_t len;      /* length of the payload */
-  uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */
-  int32_t pid;       /* generating process's pid */
-  int32_t tid;       /* generating process's tid */
-  int32_t sec;       /* seconds since Epoch */
-  int32_t nsec;      /* nanoseconds */
-  uint32_t lid;      /* log id of the payload */
-  char msg[0]; /* the entry's payload */
-} __attribute__((__packed__));
-#endif
-
-/*
- * The userspace structure for version 4 of the logger_entry ABI.
- */
-#ifndef __struct_logger_entry_v4_defined
-#define __struct_logger_entry_v4_defined
-struct logger_entry_v4 {
-  uint16_t len;      /* length of the payload */
-  uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */
+  uint16_t hdr_size; /* sizeof(struct logger_entry) */
   int32_t pid;       /* generating process's pid */
   uint32_t tid;      /* generating process's tid */
   uint32_t sec;      /* seconds since Epoch */
@@ -116,7 +61,6 @@
   uint32_t uid;      /* generating process's uid */
   char msg[0]; /* the entry's payload */
 };
-#endif
 #pragma clang diagnostic pop
 
 /*
@@ -133,16 +77,10 @@
  */
 #define LOGGER_ENTRY_MAX_LEN (5 * 1024)
 
-#ifndef __struct_log_msg_defined
-#define __struct_log_msg_defined
 struct log_msg {
   union {
     unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
-    struct logger_entry_v4 entry;
-    struct logger_entry_v4 entry_v4;
-    struct logger_entry_v3 entry_v3;
-    struct logger_entry_v2 entry_v2;
-    struct logger_entry entry_v1;
+    struct logger_entry entry;
   } __attribute__((aligned(4)));
 #ifdef __cplusplus
   /* Matching log_time operators */
@@ -176,22 +114,14 @@
   }
   char* msg() {
     unsigned short hdr_size = entry.hdr_size;
-    if (!hdr_size) {
-      hdr_size = sizeof(entry_v1);
-    }
-    if ((hdr_size < sizeof(entry_v1)) || (hdr_size > sizeof(entry))) {
+    if (hdr_size >= sizeof(struct log_msg) - sizeof(entry)) {
       return nullptr;
     }
     return reinterpret_cast<char*>(buf) + hdr_size;
   }
-  unsigned int len() {
-    return (entry.hdr_size ? entry.hdr_size
-                           : static_cast<uint16_t>(sizeof(entry_v1))) +
-           entry.len;
-  }
+  unsigned int len() { return entry.hdr_size + entry.len; }
 #endif
 };
-#endif
 
 struct logger;
 
@@ -209,8 +139,7 @@
                                       char* buf, size_t len);
 ssize_t android_logger_get_prune_list(struct logger_list* logger_list,
                                       char* buf, size_t len);
-int android_logger_set_prune_list(struct logger_list* logger_list, char* buf,
-                                  size_t len);
+int android_logger_set_prune_list(struct logger_list* logger_list, const char* buf, size_t len);
 
 #define ANDROID_LOG_RDONLY O_RDONLY
 #define ANDROID_LOG_WRONLY O_WRONLY
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 09c9910..6b4458c 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -24,9 +24,6 @@
 #define US_PER_SEC 1000000ULL
 #define MS_PER_SEC 1000ULL
 
-#ifndef __struct_log_time_defined
-#define __struct_log_time_defined
-
 #define LOG_TIME_SEC(t) ((t)->tv_sec)
 /* next power of two after NS_PER_SEC */
 #define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
@@ -35,11 +32,6 @@
 
 extern "C" {
 
-/*
- * NB: we did NOT define a copy constructor. This will result in structure
- * no longer being compatible with pass-by-value which is desired
- * efficient behavior. Also, pass-by-reference breaks C/C++ ABI.
- */
 struct log_time {
  public:
   uint32_t tv_sec = 0; /* good to Feb 5 2106 */
@@ -169,5 +161,3 @@
 } __attribute__((__packed__)) log_time;
 
 #endif /* __cplusplus */
-
-#endif /* __struct_log_time_defined */
diff --git a/liblog/include/log/log_transport.h b/liblog/include/log/log_transport.h
deleted file mode 100644
index b48761a..0000000
--- a/liblog/include/log/log_transport.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-**
-** Copyright 2017, The Android Open Source Project
-**
-** This file is dual licensed.  It may be redistributed and/or modified
-** under the terms of the Apache 2.0 License OR version 2 of the GNU
-** General Public License.
-*/
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Logging transports, bit mask to select features. Function returns selection.
- */
-/* clang-format off */
-#define LOGGER_DEFAULT 0x00
-#define LOGGER_LOGD    0x01
-#define LOGGER_KERNEL  0x02 /* Reserved/Deprecated */
-#define LOGGER_NULL    0x04 /* Does not release resources of other selections */
-#define LOGGER_RESERVED 0x08 /* Reserved, previously for logging to local memory */
-#define LOGGER_STDERR  0x10 /* logs sent to stderr */
-/* clang-format on */
-
-/* Both return the selected transport flag mask, or negative errno */
-int android_set_log_transport(int transport_flag);
-int android_get_log_transport();
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/liblog/include/log/logprint.h b/liblog/include/log/logprint.h
index 8f4b187..7dfd914 100644
--- a/liblog/include/log/logprint.h
+++ b/liblog/include/log/logprint.h
@@ -16,7 +16,8 @@
 
 #pragma once
 
-#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
 
 #include <android/log.h>
 #include <log/event_tag_map.h>
diff --git a/liblog/include/private/android_logger.h b/liblog/include/private/android_logger.h
index 5e04148..d3b72bc 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -47,7 +47,7 @@
 
 /* Header Structure to logd, and second header for pstore */
 typedef struct __attribute__((__packed__)) {
-  typeof_log_id_t id;
+  uint8_t id;
   uint16_t tid;
   log_time realtime;
 } android_log_header_t;
@@ -57,6 +57,18 @@
   int32_t tag;  // Little Endian Order
 } android_event_header_t;
 
+// Event payload EVENT_TYPE_LIST
+typedef struct __attribute__((__packed__)) {
+  int8_t type;  // EVENT_TYPE_LIST
+  int8_t element_count;
+} android_event_list_t;
+
+// Event payload EVENT_TYPE_FLOAT
+typedef struct __attribute__((__packed__)) {
+  int8_t type;  // EVENT_TYPE_FLOAT
+  float data;
+} android_event_float_t;
+
 /* Event payload EVENT_TYPE_INT */
 typedef struct __attribute__((__packed__)) {
   int8_t type;   // EVENT_TYPE_INT
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index ce4c53c..2dd8059 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -1,7 +1,7 @@
 LIBLOG {
   global:
-    android_name_to_log_id; # vndk
-    android_log_id_to_name; # vndk
+    android_name_to_log_id; # llndk
+    android_log_id_to_name; # llndk
     __android_log_assert;
     __android_log_buf_print;
     __android_log_buf_write;
@@ -14,44 +14,44 @@
 
 LIBLOG_L {
   global:
-    android_logger_clear; # vndk
-    android_logger_get_id; # vndk
-    android_logger_get_log_readable_size; # vndk
-    android_logger_get_log_version; # vndk
-    android_logger_get_log_size; # vndk
-    android_logger_list_alloc; # apex vndk
-    android_logger_list_alloc_time; # apex vndk
-    android_logger_list_free; # apex vndk
-    android_logger_list_open; # vndk
-    android_logger_list_read; # apex vndk
-    android_logger_open; # apex vndk
-    android_logger_set_log_size; # vndk
+    android_logger_clear; # llndk
+    android_logger_get_id; # llndk
+    android_logger_get_log_readable_size; # llndk
+    android_logger_get_log_version; # llndk
+    android_logger_get_log_size; # llndk
+    android_logger_list_alloc; # apex llndk
+    android_logger_list_alloc_time; # apex llndk
+    android_logger_list_free; # apex llndk
+    android_logger_list_open; # llndk
+    android_logger_list_read; # apex llndk
+    android_logger_open; # apex llndk
+    android_logger_set_log_size; # llndk
 };
 
 LIBLOG_M {
   global:
-    android_logger_get_prune_list; # vndk
-    android_logger_set_prune_list; # vndk
-    android_logger_get_statistics; # vndk
-    __android_log_error_write; # apex vndk
+    android_logger_get_prune_list; # llndk
+    android_logger_set_prune_list; # llndk
+    android_logger_get_statistics; # llndk
+    __android_log_error_write; # apex llndk
     __android_log_is_loggable;
-    create_android_logger; # apex vndk
-    android_log_destroy; # apex vndk
-    android_log_write_list_begin; # apex vndk
-    android_log_write_list_end; # apex vndk
-    android_log_write_int32; # apex vndk
-    android_log_write_int64; # apex vndk
-    android_log_write_string8; # apex vndk
-    android_log_write_string8_len; # apex vndk
-    android_log_write_float32; # apex vndk
-    android_log_write_list; # apex vndk
+    create_android_logger; # apex llndk
+    android_log_destroy; # apex llndk
+    android_log_write_list_begin; # apex llndk
+    android_log_write_list_end; # apex llndk
+    android_log_write_int32; # apex llndk
+    android_log_write_int64; # apex llndk
+    android_log_write_string8; # apex llndk
+    android_log_write_string8_len; # apex llndk
+    android_log_write_float32; # apex llndk
+    android_log_write_list; # apex llndk
 
 };
 
 LIBLOG_O {
   global:
     __android_log_is_loggable_len;
-    __android_log_is_debuggable; # vndk
+    __android_log_is_debuggable; # apex llndk
 };
 
 LIBLOG_Q {
@@ -61,15 +61,15 @@
     __android_log_bwrite; # apex
     __android_log_close; # apex
     __android_log_security; # apex
-    android_log_reset; #vndk
-    android_log_parser_reset; #vndk
+    __android_log_security_bswrite; # apex
+    android_log_reset; # llndk
+    android_log_parser_reset; # llndk
 };
 
 LIBLOG_PRIVATE {
   global:
     __android_log_pmsg_file_read;
     __android_log_pmsg_file_write;
-    __android_log_security_bswrite;
     __android_logger_get_buffer_size;
     __android_logger_property_get_bool;
     android_openEventTagMap;
diff --git a/liblog/log_event_list.cpp b/liblog/log_event_list.cpp
index b1b527c..e9f4a32 100644
--- a/liblog/log_event_list.cpp
+++ b/liblog/log_event_list.cpp
@@ -47,15 +47,10 @@
   uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
 };
 
-// TODO(tomcherry): real C++ structs.
-typedef struct android_log_context_internal android_log_context_internal;
-
 static void init_context(android_log_context_internal* context, uint32_t tag) {
-  size_t needed;
-
   context->tag = tag;
   context->read_write_flag = kAndroidLoggerWrite;
-  needed = sizeof(uint8_t) + sizeof(uint8_t);
+  size_t needed = sizeof(android_event_list_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
   }
@@ -88,7 +83,6 @@
 
 android_log_context create_android_log_parser(const char* msg, size_t len) {
   android_log_context_internal* context;
-  size_t i;
 
   context =
       static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
@@ -113,11 +107,9 @@
   return 0;
 }
 
-int android_log_reset(android_log_context ctx) {
-  android_log_context_internal* context;
+int android_log_reset(android_log_context context) {
   uint32_t tag;
 
-  context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -129,10 +121,7 @@
   return 0;
 }
 
-int android_log_parser_reset(android_log_context ctx, const char* msg, size_t len) {
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_parser_reset(android_log_context context, const char* msg, size_t len) {
   if (!context || (kAndroidLoggerRead != context->read_write_flag)) {
     return -EBADF;
   }
@@ -143,11 +132,7 @@
   return 0;
 }
 
-int android_log_write_list_begin(android_log_context ctx) {
-  size_t needed;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_write_list_begin(android_log_context context) {
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -155,7 +140,7 @@
     context->overflow = true;
     return -EOVERFLOW;
   }
-  needed = sizeof(uint8_t) + sizeof(uint8_t);
+  size_t needed = sizeof(android_event_list_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
@@ -169,84 +154,56 @@
   if (context->overflow) {
     return -EIO;
   }
-  context->storage[context->pos + 0] = EVENT_TYPE_LIST;
-  context->storage[context->pos + 1] = 0;
+  auto* event_list = reinterpret_cast<android_event_list_t*>(&context->storage[context->pos]);
+  event_list->type = EVENT_TYPE_LIST;
+  event_list->element_count = 0;
   context->list[context->list_nest_depth] = context->pos + 1;
   context->count[context->list_nest_depth] = 0;
   context->pos += needed;
   return 0;
 }
 
-static inline void copy4LE(uint8_t* buf, uint32_t val) {
-  buf[0] = val & 0xFF;
-  buf[1] = (val >> 8) & 0xFF;
-  buf[2] = (val >> 16) & 0xFF;
-  buf[3] = (val >> 24) & 0xFF;
-}
-
-int android_log_write_int32(android_log_context ctx, int32_t value) {
-  size_t needed;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_write_int32(android_log_context context, int32_t value) {
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
   if (context->overflow) {
     return -EIO;
   }
-  needed = sizeof(uint8_t) + sizeof(value);
+  size_t needed = sizeof(android_event_int_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
   }
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_INT;
-  copy4LE(&context->storage[context->pos + 1], value);
+  auto* event_int = reinterpret_cast<android_event_int_t*>(&context->storage[context->pos]);
+  event_int->type = EVENT_TYPE_INT;
+  event_int->data = value;
   context->pos += needed;
   return 0;
 }
 
-static inline void copy8LE(uint8_t* buf, uint64_t val) {
-  buf[0] = val & 0xFF;
-  buf[1] = (val >> 8) & 0xFF;
-  buf[2] = (val >> 16) & 0xFF;
-  buf[3] = (val >> 24) & 0xFF;
-  buf[4] = (val >> 32) & 0xFF;
-  buf[5] = (val >> 40) & 0xFF;
-  buf[6] = (val >> 48) & 0xFF;
-  buf[7] = (val >> 56) & 0xFF;
-}
-
-int android_log_write_int64(android_log_context ctx, int64_t value) {
-  size_t needed;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_write_int64(android_log_context context, int64_t value) {
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
   if (context->overflow) {
     return -EIO;
   }
-  needed = sizeof(uint8_t) + sizeof(value);
+  size_t needed = sizeof(android_event_long_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
   }
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_LONG;
-  copy8LE(&context->storage[context->pos + 1], value);
+  auto* event_long = reinterpret_cast<android_event_long_t*>(&context->storage[context->pos]);
+  event_long->type = EVENT_TYPE_LONG;
+  event_long->data = value;
   context->pos += needed;
   return 0;
 }
 
-int android_log_write_string8_len(android_log_context ctx, const char* value, size_t maxlen) {
-  size_t needed;
-  ssize_t len;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_write_string8_len(android_log_context context, const char* value, size_t maxlen) {
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -256,8 +213,8 @@
   if (!value) {
     value = "";
   }
-  len = strnlen(value, maxlen);
-  needed = sizeof(uint8_t) + sizeof(int32_t) + len;
+  int32_t len = strnlen(value, maxlen);
+  size_t needed = sizeof(android_event_string_t) + len;
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     /* Truncate string for delivery */
     len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
@@ -267,10 +224,11 @@
     }
   }
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_STRING;
-  copy4LE(&context->storage[context->pos + 1], len);
+  auto* event_string = reinterpret_cast<android_event_string_t*>(&context->storage[context->pos]);
+  event_string->type = EVENT_TYPE_STRING;
+  event_string->length = len;
   if (len) {
-    memcpy(&context->storage[context->pos + 5], value, len);
+    memcpy(&event_string->data, value, len);
   }
   context->pos += needed;
   return len;
@@ -280,35 +238,27 @@
   return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
 }
 
-int android_log_write_float32(android_log_context ctx, float value) {
-  size_t needed;
-  uint32_t ivalue;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_write_float32(android_log_context context, float value) {
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
   if (context->overflow) {
     return -EIO;
   }
-  needed = sizeof(uint8_t) + sizeof(ivalue);
+  size_t needed = sizeof(android_event_float_t);
   if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
     context->overflow = true;
     return -EIO;
   }
-  ivalue = *(uint32_t*)&value;
   context->count[context->list_nest_depth]++;
-  context->storage[context->pos + 0] = EVENT_TYPE_FLOAT;
-  copy4LE(&context->storage[context->pos + 1], ivalue);
+  auto* event_float = reinterpret_cast<android_event_float_t*>(&context->storage[context->pos]);
+  event_float->type = EVENT_TYPE_FLOAT;
+  event_float->data = value;
   context->pos += needed;
   return 0;
 }
 
-int android_log_write_list_end(android_log_context ctx) {
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
+int android_log_write_list_end(android_log_context context) {
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -335,8 +285,7 @@
 /*
  * Logs the list of elements to the event log.
  */
-int android_log_write_list(android_log_context ctx, log_id_t id) {
-  android_log_context_internal* context;
+int android_log_write_list(android_log_context context, log_id_t id) {
   const char* msg;
   ssize_t len;
 
@@ -344,7 +293,6 @@
     return -EINVAL;
   }
 
-  context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -369,12 +317,10 @@
                                      : __android_log_security_bwrite(context->tag, msg, len));
 }
 
-int android_log_write_list_buffer(android_log_context ctx, const char** buffer) {
-  android_log_context_internal* context;
+int android_log_write_list_buffer(android_log_context context, const char** buffer) {
   const char* msg;
   ssize_t len;
 
-  context = (android_log_context_internal*)ctx;
   if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
     return -EBADF;
   }
@@ -401,34 +347,16 @@
 }
 
 /*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-/*
- * Extract an 8-byte value from a byte stream.
- */
-static inline uint64_t get8LE(const uint8_t* src) {
-  uint32_t low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-  uint32_t high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-  return ((uint64_t)high << 32) | (uint64_t)low;
-}
-
-/*
  * Gets the next element. Parsing errors result in an EVENT_TYPE_UNKNOWN type.
  * If there is nothing to process, the complete field is set to non-zero. If
  * an EVENT_TYPE_UNKNOWN type is returned once, and the caller does not check
  * this and continues to call this function, the behavior is undefined
  * (although it won't crash).
  */
-static android_log_list_element android_log_read_next_internal(android_log_context ctx, int peek) {
+static android_log_list_element android_log_read_next_internal(android_log_context context,
+                                                               int peek) {
   android_log_list_element elem;
   unsigned pos;
-  android_log_context_internal* context;
-
-  context = (android_log_context_internal*)ctx;
 
   memset(&elem, 0, sizeof(elem));
 
@@ -478,20 +406,22 @@
     return elem;
   }
 
-  elem.type = static_cast<AndroidEventLogType>(context->storage[pos++]);
+  elem.type = static_cast<AndroidEventLogType>(context->storage[pos]);
   switch ((int)elem.type) {
     case EVENT_TYPE_FLOAT:
     /* Rely on union to translate elem.data.int32 into elem.data.float32 */
     /* FALLTHRU */
-    case EVENT_TYPE_INT:
+    case EVENT_TYPE_INT: {
       elem.len = sizeof(int32_t);
-      if ((pos + elem.len) > context->len) {
+      if ((pos + sizeof(android_event_int_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         return elem;
       }
-      elem.data.int32 = get4LE(&context->storage[pos]);
+
+      auto* event_int = reinterpret_cast<android_event_int_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_int_t);
+      elem.data.int32 = event_int->data;
       /* common tangeable object suffix */
-      pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
       if (!peek) {
         if (!context->count[context->list_nest_depth] ||
@@ -501,16 +431,19 @@
         context->pos = pos;
       }
       return elem;
+    }
 
-    case EVENT_TYPE_LONG:
+    case EVENT_TYPE_LONG: {
       elem.len = sizeof(int64_t);
-      if ((pos + elem.len) > context->len) {
+      if ((pos + sizeof(android_event_long_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         return elem;
       }
-      elem.data.int64 = get8LE(&context->storage[pos]);
+
+      auto* event_long = reinterpret_cast<android_event_long_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_long_t);
+      elem.data.int64 = event_long->data;
       /* common tangeable object suffix */
-      pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
       if (!peek) {
         if (!context->count[context->list_nest_depth] ||
@@ -520,15 +453,22 @@
         context->pos = pos;
       }
       return elem;
+    }
 
-    case EVENT_TYPE_STRING:
-      if ((pos + sizeof(int32_t)) > context->len) {
+    case EVENT_TYPE_STRING: {
+      if ((pos + sizeof(android_event_string_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         elem.complete = true;
         return elem;
       }
-      elem.len = get4LE(&context->storage[pos]);
-      pos += sizeof(int32_t);
+      auto* event_string = reinterpret_cast<android_event_string_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_string_t);
+      // Wire format is int32_t, but elem.len is uint16_t...
+      if (event_string->length >= UINT16_MAX) {
+        elem.type = EVENT_TYPE_UNKNOWN;
+        return elem;
+      }
+      elem.len = event_string->length;
       if ((pos + elem.len) > context->len) {
         elem.len = context->len - pos; /* truncate string */
         elem.complete = true;
@@ -537,7 +477,7 @@
           return elem;
         }
       }
-      elem.data.string = (char*)&context->storage[pos];
+      elem.data.string = event_string->data;
       /* common tangeable object suffix */
       pos += elem.len;
       elem.complete = !context->list_nest_depth && !context->count[0];
@@ -549,13 +489,16 @@
         context->pos = pos;
       }
       return elem;
+    }
 
-    case EVENT_TYPE_LIST:
-      if ((pos + sizeof(uint8_t)) > context->len) {
+    case EVENT_TYPE_LIST: {
+      if ((pos + sizeof(android_event_list_t)) > context->len) {
         elem.type = EVENT_TYPE_UNKNOWN;
         elem.complete = true;
         return elem;
       }
+      auto* event_list = reinterpret_cast<android_event_list_t*>(&context->storage[pos]);
+      pos += sizeof(android_event_list_t);
       elem.complete = context->list_nest_depth >= ANDROID_MAX_LIST_NEST_DEPTH;
       if (peek) {
         return elem;
@@ -563,15 +506,17 @@
       if (context->count[context->list_nest_depth]) {
         context->count[context->list_nest_depth]--;
       }
-      context->list_stop = !context->storage[pos];
+      context->list_stop = event_list->element_count == 0;
       context->list_nest_depth++;
       if (context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) {
-        context->count[context->list_nest_depth] = context->storage[pos];
+        context->count[context->list_nest_depth] = event_list->element_count;
       }
-      context->pos = pos + sizeof(uint8_t);
+      context->pos = pos;
       return elem;
+    }
 
     case EVENT_TYPE_LIST_STOP: /* Suprise Newline terminates lists. */
+      pos++;
       if (!peek) {
         context->pos = pos;
       }
diff --git a/liblog/log_portability.h b/liblog/log_portability.h
index 468a498..b7279d1 100644
--- a/liblog/log_portability.h
+++ b/liblog/log_portability.h
@@ -19,16 +19,6 @@
 #include <sys/cdefs.h>
 #include <unistd.h>
 
-/*
- * Declare this library function as reimplementation.
- * Prevent circular dependencies, but allow _real_ library to hijack
- */
-#if defined(_WIN32)
-#define LIBLOG_WEAK static /* Accept that it is totally private */
-#else
-#define LIBLOG_WEAK extern "C" __attribute__((weak, visibility("default")))
-#endif
-
 /* possible missing definitions in sys/cdefs.h */
 
 /* DECLS */
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index b7ba782..6865c14 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-#include <endian.h>
+#include "logd_reader.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -24,6 +25,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -31,75 +33,14 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <string>
+
 #include <cutils/sockets.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#include "config_read.h"
-#include "log_portability.h"
-#include "logd_reader.h"
 #include "logger.h"
 
-/* branchless on many architectures. */
-#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
-
-static int logdAvailable(log_id_t LogId);
-static int logdVersion(struct android_log_logger* logger,
-                       struct android_log_transport_context* transp);
-static int logdRead(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp, struct log_msg* log_msg);
-static int logdPoll(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp);
-static void logdClose(struct android_log_logger_list* logger_list,
-                      struct android_log_transport_context* transp);
-static int logdClear(struct android_log_logger* logger,
-                     struct android_log_transport_context* transp);
-static ssize_t logdSetSize(struct android_log_logger* logger,
-                           struct android_log_transport_context* transp, size_t size);
-static ssize_t logdGetSize(struct android_log_logger* logger,
-                           struct android_log_transport_context* transp);
-static ssize_t logdGetReadableSize(struct android_log_logger* logger,
-                                   struct android_log_transport_context* transp);
-static ssize_t logdGetPrune(struct android_log_logger_list* logger,
-                            struct android_log_transport_context* transp, char* buf, size_t len);
-static ssize_t logdSetPrune(struct android_log_logger_list* logger,
-                            struct android_log_transport_context* transp, char* buf, size_t len);
-static ssize_t logdGetStats(struct android_log_logger_list* logger,
-                            struct android_log_transport_context* transp, char* buf, size_t len);
-
-struct android_log_transport_read logdLoggerRead = {
-    .node = {&logdLoggerRead.node, &logdLoggerRead.node},
-    .name = "logd",
-    .available = logdAvailable,
-    .version = logdVersion,
-    .read = logdRead,
-    .poll = logdPoll,
-    .close = logdClose,
-    .clear = logdClear,
-    .getSize = logdGetSize,
-    .setSize = logdSetSize,
-    .getReadableSize = logdGetReadableSize,
-    .getPrune = logdGetPrune,
-    .setPrune = logdSetPrune,
-    .getStats = logdGetStats,
-};
-
-static int logdAvailable(log_id_t logId) {
-  if (logId >= LOG_ID_MAX) {
-    return -EINVAL;
-  }
-  if (logId == LOG_ID_SECURITY) {
-    uid_t uid = __android_log_uid();
-    if (uid != AID_SYSTEM) {
-      return -EPERM;
-    }
-  }
-  if (access("/dev/socket/logdw", W_OK) == 0) {
-    return 0;
-  }
-  return -EBADF;
-}
-
 // Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
 // O_CLOEXEC is always set.
 static int socket_local_client(const std::string& name, int type) {
@@ -112,7 +53,7 @@
   strlcpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path));
 
   int fd = socket(AF_LOCAL, type | SOCK_CLOEXEC, 0);
-  if (fd == 0) {
+  if (fd == -1) {
     return -1;
   }
 
@@ -125,8 +66,7 @@
 }
 
 /* worker for sending the command to the logger */
-static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
-                            size_t buf_size) {
+ssize_t SendLogdControlMessage(char* buf, size_t buf_size) {
   ssize_t ret;
   size_t len;
   char* cp;
@@ -136,10 +76,6 @@
     return sock;
   }
 
-  if (msg) {
-    snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned)-1);
-  }
-
   len = strlen(buf) + 1;
   ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
   if (ret <= 0) {
@@ -190,10 +126,6 @@
   return ret;
 }
 
-ssize_t __send_log_msg(char* buf, size_t buf_size) {
-  return send_log_msg(NULL, NULL, buf, buf_size);
-}
-
 static int check_log_success(char* buf, ssize_t ret) {
   if (ret < 0) {
     return ret;
@@ -207,19 +139,28 @@
   return 0;
 }
 
-static int logdClear(struct android_log_logger* logger,
-                     struct android_log_transport_context* transp __unused) {
+int android_logger_clear(struct logger* logger) {
+  if (!android_logger_is_logd(logger)) {
+    return -EINVAL;
+  }
+  uint32_t log_id = android_logger_get_id(logger);
   char buf[512];
+  snprintf(buf, sizeof(buf), "clear %" PRIu32, log_id);
 
-  return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
+  return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
 }
 
 /* returns the total size of the log's ring buffer */
-static ssize_t logdGetSize(struct android_log_logger* logger,
-                           struct android_log_transport_context* transp __unused) {
-  char buf[512];
+long android_logger_get_log_size(struct logger* logger) {
+  if (!android_logger_is_logd(logger)) {
+    return -EINVAL;
+  }
 
-  ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
+  uint32_t log_id = android_logger_get_id(logger);
+  char buf[512];
+  snprintf(buf, sizeof(buf), "getLogSize %" PRIu32, log_id);
+
+  ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
   if (ret < 0) {
     return ret;
   }
@@ -231,24 +172,32 @@
   return atol(buf);
 }
 
-static ssize_t logdSetSize(struct android_log_logger* logger,
-                           struct android_log_transport_context* transp __unused, size_t size) {
+int android_logger_set_log_size(struct logger* logger, unsigned long size) {
+  if (!android_logger_is_logd(logger)) {
+    return -EINVAL;
+  }
+
+  uint32_t log_id = android_logger_get_id(logger);
   char buf[512];
+  snprintf(buf, sizeof(buf), "setLogSize %" PRIu32 " %lu", log_id, size);
 
-  snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
-
-  return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
+  return check_log_success(buf, SendLogdControlMessage(buf, sizeof(buf)));
 }
 
 /*
  * returns the readable size of the log's ring buffer (that is, amount of the
  * log consumed)
  */
-static ssize_t logdGetReadableSize(struct android_log_logger* logger,
-                                   struct android_log_transport_context* transp __unused) {
-  char buf[512];
+long android_logger_get_log_readable_size(struct logger* logger) {
+  if (!android_logger_is_logd(logger)) {
+    return -EINVAL;
+  }
 
-  ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
+  uint32_t log_id = android_logger_get_id(logger);
+  char buf[512];
+  snprintf(buf, sizeof(buf), "getLogSizeUsed %" PRIu32, log_id);
+
+  ssize_t ret = SendLogdControlMessage(buf, sizeof(buf));
   if (ret < 0) {
     return ret;
   }
@@ -260,94 +209,68 @@
   return atol(buf);
 }
 
-/*
- * returns the logger version
- */
-static int logdVersion(struct android_log_logger* logger __unused,
-                       struct android_log_transport_context* transp __unused) {
-  uid_t uid = __android_log_uid();
-  return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
+int android_logger_get_log_version(struct logger*) {
+  return 4;
 }
 
-/*
- * returns statistics
- */
-static ssize_t logdGetStats(struct android_log_logger_list* logger_list,
-                            struct android_log_transport_context* transp __unused, char* buf,
-                            size_t len) {
-  struct android_log_logger* logger;
+ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
+  if (logger_list->mode & ANDROID_LOG_PSTORE) {
+    return -EINVAL;
+  }
+
   char* cp = buf;
   size_t remaining = len;
   size_t n;
 
   n = snprintf(cp, remaining, "getStatistics");
-  n = min(n, remaining);
+  n = MIN(n, remaining);
   remaining -= n;
   cp += n;
 
-  logger_for_each(logger, logger_list) {
-    n = snprintf(cp, remaining, " %d", logger->logId);
-    n = min(n, remaining);
-    remaining -= n;
-    cp += n;
+  for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
+    if ((1 << log_id) & logger_list->log_mask) {
+      n = snprintf(cp, remaining, " %zu", log_id);
+      n = MIN(n, remaining);
+      remaining -= n;
+      cp += n;
+    }
   }
 
   if (logger_list->pid) {
     snprintf(cp, remaining, " pid=%u", logger_list->pid);
   }
 
-  return send_log_msg(NULL, NULL, buf, len);
+  return SendLogdControlMessage(buf, len);
 }
-
-static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
-                            struct android_log_transport_context* transp __unused, char* buf,
-                            size_t len) {
-  return send_log_msg(NULL, "getPruneList", buf, len);
-}
-
-static ssize_t logdSetPrune(struct android_log_logger_list* logger_list __unused,
-                            struct android_log_transport_context* transp __unused, char* buf,
-                            size_t len) {
-  const char cmd[] = "setPruneList ";
-  const size_t cmdlen = sizeof(cmd) - 1;
-
-  if (strlen(buf) > (len - cmdlen)) {
-    return -ENOMEM; /* KISS */
-  }
-  memmove(buf + cmdlen, buf, len - cmdlen);
-  buf[len - 1] = '\0';
-  memcpy(buf, cmd, cmdlen);
-
-  return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
-}
-
-static void caught_signal(int signum __unused) {}
-
-static int logdOpen(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp) {
-  struct android_log_logger* logger;
-  struct sigaction ignore;
-  struct sigaction old_sigaction;
-  unsigned int old_alarm = 0;
-  char buffer[256], *cp, c;
-  int e, ret, remaining, sock;
-
-  if (!logger_list) {
+ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
+  if (logger_list->mode & ANDROID_LOG_PSTORE) {
     return -EINVAL;
   }
 
-  sock = atomic_load(&transp->context.sock);
+  snprintf(buf, len, "getPruneList");
+  return SendLogdControlMessage(buf, len);
+}
+
+int android_logger_set_prune_list(struct logger_list* logger_list, const char* buf, size_t len) {
+  if (logger_list->mode & ANDROID_LOG_PSTORE) {
+    return -EINVAL;
+  }
+
+  std::string cmd = "setPruneList " + std::string{buf, len};
+
+  return check_log_success(cmd.data(), SendLogdControlMessage(cmd.data(), cmd.size()));
+}
+
+static int logdOpen(struct logger_list* logger_list) {
+  char buffer[256], *cp, c;
+  int ret, remaining, sock;
+
+  sock = atomic_load(&logger_list->fd);
   if (sock > 0) {
     return sock;
   }
 
   sock = socket_local_client("logdr", SOCK_SEQPACKET);
-  if (sock == 0) {
-    /* Guarantee not file descriptor zero */
-    int newsock = socket_local_client("logdr", SOCK_SEQPACKET);
-    close(sock);
-    sock = newsock;
-  }
   if (sock <= 0) {
     if ((sock == -1) && errno) {
       return -errno;
@@ -362,17 +285,20 @@
   cp += 5;
   c = '=';
   remaining = sizeof(buffer) - (cp - buffer);
-  logger_for_each(logger, logger_list) {
-    ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
-    ret = min(ret, remaining);
-    remaining -= ret;
-    cp += ret;
-    c = ',';
+
+  for (size_t log_id = 0; log_id < LOG_ID_MAX; ++log_id) {
+    if ((1 << log_id) & logger_list->log_mask) {
+      ret = snprintf(cp, remaining, "%c%zu", c, log_id);
+      ret = MIN(ret, remaining);
+      remaining -= ret;
+      cp += ret;
+      c = ',';
+    }
   }
 
   if (logger_list->tail) {
     ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
-    ret = min(ret, remaining);
+    ret = MIN(ret, remaining);
     remaining -= ret;
     cp += ret;
   }
@@ -381,46 +307,30 @@
     if (logger_list->mode & ANDROID_LOG_WRAP) {
       // ToDo: alternate API to allow timeout to be adjusted.
       ret = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
-      ret = min(ret, remaining);
+      ret = MIN(ret, remaining);
       remaining -= ret;
       cp += ret;
     }
     ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec,
                    logger_list->start.tv_nsec);
-    ret = min(ret, remaining);
+    ret = MIN(ret, remaining);
     remaining -= ret;
     cp += ret;
   }
 
   if (logger_list->pid) {
     ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
-    ret = min(ret, remaining);
+    ret = MIN(ret, remaining);
     cp += ret;
   }
 
-  if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
-    /* Deal with an unresponsive logd */
-    memset(&ignore, 0, sizeof(ignore));
-    ignore.sa_handler = caught_signal;
-    sigemptyset(&ignore.sa_mask);
-    /* particularily useful if tombstone is reporting for logd */
-    sigaction(SIGALRM, &ignore, &old_sigaction);
-    old_alarm = alarm(30);
-  }
-  ret = write(sock, buffer, cp - buffer);
-  e = errno;
-  if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
-    if (e == EINTR) {
-      e = ETIMEDOUT;
-    }
-    alarm(old_alarm);
-    sigaction(SIGALRM, &old_sigaction, NULL);
-  }
+  ret = TEMP_FAILURE_RETRY(write(sock, buffer, cp - buffer));
+  int write_errno = errno;
 
   if (ret <= 0) {
     close(sock);
-    if ((ret == -1) && e) {
-      return -e;
+    if (ret == -1) {
+      return -write_errno;
     }
     if (ret == 0) {
       return -EIO;
@@ -428,7 +338,7 @@
     return ret;
   }
 
-  ret = atomic_exchange(&transp->context.sock, sock);
+  ret = atomic_exchange(&logger_list->fd, sock);
   if ((ret > 0) && (ret != sock)) {
     close(ret);
   }
@@ -436,84 +346,27 @@
 }
 
 /* Read from the selected logs */
-static int logdRead(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp, struct log_msg* log_msg) {
-  int ret, e;
-  struct sigaction ignore;
-  struct sigaction old_sigaction;
-  unsigned int old_alarm = 0;
-
-  ret = logdOpen(logger_list, transp);
+int LogdRead(struct logger_list* logger_list, struct log_msg* log_msg) {
+  int ret = logdOpen(logger_list);
   if (ret < 0) {
     return ret;
   }
 
-  memset(log_msg, 0, sizeof(*log_msg));
-
-  unsigned int new_alarm = 0;
-  if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
-    if ((logger_list->mode & ANDROID_LOG_WRAP) &&
-        (logger_list->start.tv_sec || logger_list->start.tv_nsec)) {
-      /* b/64143705 */
-      new_alarm = (ANDROID_LOG_WRAP_DEFAULT_TIMEOUT * 11) / 10 + 10;
-      logger_list->mode &= ~ANDROID_LOG_WRAP;
-    } else {
-      new_alarm = 30;
-    }
-
-    memset(&ignore, 0, sizeof(ignore));
-    ignore.sa_handler = caught_signal;
-    sigemptyset(&ignore.sa_mask);
-    /* particularily useful if tombstone is reporting for logd */
-    sigaction(SIGALRM, &ignore, &old_sigaction);
-    old_alarm = alarm(new_alarm);
-  }
-
   /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
-  ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
-  e = errno;
-
-  if (new_alarm) {
-    if ((ret == 0) || (e == EINTR)) {
-      e = EAGAIN;
-      ret = -1;
-    }
-    alarm(old_alarm);
-    sigaction(SIGALRM, &old_sigaction, NULL);
+  ret = TEMP_FAILURE_RETRY(recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0));
+  if ((logger_list->mode & ANDROID_LOG_NONBLOCK) && ret == 0) {
+    return -EAGAIN;
   }
 
-  if ((ret == -1) && e) {
-    return -e;
-  }
-  return ret;
-}
-
-static int logdPoll(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp) {
-  struct pollfd p;
-
-  int ret = logdOpen(logger_list, transp);
-  if (ret < 0) {
-    return ret;
-  }
-
-  memset(&p, 0, sizeof(p));
-  p.fd = ret;
-  p.events = POLLIN;
-  ret = poll(&p, 1, 20);
-  if ((ret > 0) && !(p.revents & POLLIN)) {
-    ret = 0;
-  }
-  if ((ret == -1) && errno) {
+  if (ret == -1) {
     return -errno;
   }
   return ret;
 }
 
 /* Close all the logs */
-static void logdClose(struct android_log_logger_list* logger_list __unused,
-                      struct android_log_transport_context* transp) {
-  int sock = atomic_exchange(&transp->context.sock, -1);
+void LogdClose(struct logger_list* logger_list) {
+  int sock = atomic_exchange(&logger_list->fd, -1);
   if (sock > 0) {
     close(sock);
   }
diff --git a/liblog/logd_reader.h b/liblog/logd_reader.h
index 7c53cbb..2d032fa 100644
--- a/liblog/logd_reader.h
+++ b/liblog/logd_reader.h
@@ -18,10 +18,14 @@
 
 #include <unistd.h>
 
+#include "log/log_read.h"
 #include "log_portability.h"
 
 __BEGIN_DECLS
 
-ssize_t __send_log_msg(char* buf, size_t buf_size);
+int LogdRead(struct logger_list* logger_list, struct log_msg* log_msg);
+void LogdClose(struct logger_list* logger_list);
+
+ssize_t SendLogdControlMessage(char* buf, size_t buf_size);
 
 __END_DECLS
diff --git a/liblog/logd_writer.cpp b/liblog/logd_writer.cpp
index c3f72f4..3c6eb69 100644
--- a/liblog/logd_writer.cpp
+++ b/liblog/logd_writer.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <endian.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -31,101 +30,76 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <shared_mutex>
+
 #include <cutils/sockets.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#include "config_write.h"
 #include "log_portability.h"
 #include "logger.h"
+#include "rwlock.h"
 #include "uio.h"
 
-/* branchless on many architectures. */
-#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
-
-static int logdAvailable(log_id_t LogId);
-static int logdOpen();
-static void logdClose();
-static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
+static int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
+static void LogdClose();
 
 struct android_log_transport_write logdLoggerWrite = {
-    .node = {&logdLoggerWrite.node, &logdLoggerWrite.node},
-    .context.sock = -EBADF,
-    .name = "logd",
-    .available = logdAvailable,
-    .open = logdOpen,
-    .close = logdClose,
-    .write = logdWrite,
+    .close = LogdClose,
+    .write = LogdWrite,
 };
 
-/* log_init_lock assumed */
-static int logdOpen() {
-  int i, ret = 0;
+static int logd_socket;
+static RwLock logd_socket_lock;
 
-  i = atomic_load(&logdLoggerWrite.context.sock);
-  if (i < 0) {
-    int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
-    if (sock < 0) {
-      ret = -errno;
-    } else {
-      struct sockaddr_un un;
-      memset(&un, 0, sizeof(struct sockaddr_un));
-      un.sun_family = AF_UNIX;
-      strcpy(un.sun_path, "/dev/socket/logdw");
-
-      if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) <
-          0) {
-        ret = -errno;
-        switch (ret) {
-          case -ENOTCONN:
-          case -ECONNREFUSED:
-          case -ENOENT:
-            i = atomic_exchange(&logdLoggerWrite.context.sock, ret);
-            [[fallthrough]];
-          default:
-            break;
-        }
-        close(sock);
-      } else {
-        ret = atomic_exchange(&logdLoggerWrite.context.sock, sock);
-        if ((ret >= 0) && (ret != sock)) {
-          close(ret);
-        }
-        ret = 0;
-      }
-    }
+static void OpenSocketLocked() {
+  logd_socket = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+  if (logd_socket <= 0) {
+    return;
   }
 
-  return ret;
-}
+  sockaddr_un un = {};
+  un.sun_family = AF_UNIX;
+  strcpy(un.sun_path, "/dev/socket/logdw");
 
-static void __logdClose(int negative_errno) {
-  int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno);
-  if (sock >= 0) {
-    close(sock);
+  if (TEMP_FAILURE_RETRY(
+          connect(logd_socket, reinterpret_cast<sockaddr*>(&un), sizeof(sockaddr_un))) < 0) {
+    close(logd_socket);
+    logd_socket = 0;
   }
 }
 
-static void logdClose() {
-  __logdClose(-EBADF);
+static void OpenSocket() {
+  auto lock = std::unique_lock{logd_socket_lock};
+  if (logd_socket > 0) {
+    // Someone raced us and opened the socket already.
+    return;
+  }
+
+  OpenSocketLocked();
 }
 
-static int logdAvailable(log_id_t logId) {
-  if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) {
-    return -EINVAL;
+static void ResetSocket(int old_socket) {
+  auto lock = std::unique_lock{logd_socket_lock};
+  if (old_socket != logd_socket) {
+    // Someone raced us and reset the socket already.
+    return;
   }
-  if (atomic_load(&logdLoggerWrite.context.sock) < 0) {
-    if (access("/dev/socket/logdw", W_OK) == 0) {
-      return 0;
-    }
-    return -EBADF;
-  }
-  return 1;
+  close(logd_socket);
+  logd_socket = 0;
+  OpenSocketLocked();
 }
 
-static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
+static void LogdClose() {
+  auto lock = std::unique_lock{logd_socket_lock};
+  if (logd_socket > 0) {
+    close(logd_socket);
+  }
+  logd_socket = 0;
+}
+
+static int LogdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
   ssize_t ret;
-  int sock;
   static const unsigned headerLength = 1;
   struct iovec newVec[nr + headerLength];
   android_log_header_t header;
@@ -133,15 +107,16 @@
   static atomic_int dropped;
   static atomic_int droppedSecurity;
 
-  sock = atomic_load(&logdLoggerWrite.context.sock);
-  if (sock < 0) switch (sock) {
-      case -ENOTCONN:
-      case -ECONNREFUSED:
-      case -ENOENT:
-        break;
-      default:
-        return -EBADF;
-    }
+  auto lock = std::shared_lock{logd_socket_lock};
+  if (logd_socket <= 0) {
+    lock.unlock();
+    OpenSocket();
+    lock.lock();
+  }
+
+  if (logd_socket <= 0) {
+    return -EBADF;
+  }
 
   /* logd, after initialization and priv drop */
   if (__android_log_uid() == AID_LOGD) {
@@ -153,24 +128,6 @@
     return 0;
   }
 
-  /*
-   *  struct {
-   *      // what we provide to socket
-   *      android_log_header_t header;
-   *      // caller provides
-   *      union {
-   *          struct {
-   *              char     prio;
-   *              char     payload[];
-   *          } string;
-   *          struct {
-   *              uint32_t tag
-   *              char     payload[];
-   *          } binary;
-   *      };
-   *  };
-   */
-
   header.tid = gettid();
   header.realtime.tv_sec = ts->tv_sec;
   header.realtime.tv_nsec = ts->tv_nsec;
@@ -178,41 +135,39 @@
   newVec[0].iov_base = (unsigned char*)&header;
   newVec[0].iov_len = sizeof(header);
 
-  if (sock >= 0) {
-    int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
-    if (snapshot) {
-      android_log_event_int_t buffer;
+  int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
+  if (snapshot) {
+    android_log_event_int_t buffer;
 
-      header.id = LOG_ID_SECURITY;
-      buffer.header.tag = htole32(LIBLOG_LOG_TAG);
-      buffer.payload.type = EVENT_TYPE_INT;
-      buffer.payload.data = htole32(snapshot);
+    header.id = LOG_ID_SECURITY;
+    buffer.header.tag = LIBLOG_LOG_TAG;
+    buffer.payload.type = EVENT_TYPE_INT;
+    buffer.payload.data = snapshot;
 
-      newVec[headerLength].iov_base = &buffer;
-      newVec[headerLength].iov_len = sizeof(buffer);
+    newVec[headerLength].iov_base = &buffer;
+    newVec[headerLength].iov_len = sizeof(buffer);
 
-      ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
-      if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
-        atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
-      }
+    ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
+    if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+      atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
     }
-    snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
-    if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
-                                                  ANDROID_LOG_VERBOSE)) {
-      android_log_event_int_t buffer;
+  }
+  snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
+  if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
+                                                ANDROID_LOG_VERBOSE)) {
+    android_log_event_int_t buffer;
 
-      header.id = LOG_ID_EVENTS;
-      buffer.header.tag = htole32(LIBLOG_LOG_TAG);
-      buffer.payload.type = EVENT_TYPE_INT;
-      buffer.payload.data = htole32(snapshot);
+    header.id = LOG_ID_EVENTS;
+    buffer.header.tag = LIBLOG_LOG_TAG;
+    buffer.payload.type = EVENT_TYPE_INT;
+    buffer.payload.data = snapshot;
 
-      newVec[headerLength].iov_base = &buffer;
-      newVec[headerLength].iov_len = sizeof(buffer);
+    newVec[headerLength].iov_base = &buffer;
+    newVec[headerLength].iov_len = sizeof(buffer);
 
-      ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
-      if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
-        atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
-      }
+    ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
+    if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+      atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
     }
   }
 
@@ -231,49 +186,26 @@
     }
   }
 
-  /*
-   * The write below could be lost, but will never block.
-   *
-   * ENOTCONN occurs if logd has died.
-   * ENOENT occurs if logd is not running and socket is missing.
-   * ECONNREFUSED occurs if we can not reconnect to logd.
-   * EAGAIN occurs if logd is overloaded.
-   */
-  if (sock < 0) {
-    ret = sock;
-  } else {
-    ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i));
-    if (ret < 0) {
-      ret = -errno;
-    }
+  // The write below could be lost, but will never block.
+  // EAGAIN occurs if logd is overloaded, other errors indicate that something went wrong with
+  // the connection, so we reset it and try again.
+  ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
+  if (ret < 0 && errno != EAGAIN) {
+    int old_socket = logd_socket;
+    lock.unlock();
+    ResetSocket(old_socket);
+    lock.lock();
+
+    ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
   }
-  switch (ret) {
-    case -ENOTCONN:
-    case -ECONNREFUSED:
-    case -ENOENT:
-      if (__android_log_trylock()) {
-        return ret; /* in a signal handler? try again when less stressed */
-      }
-      __logdClose(ret);
-      ret = logdOpen();
-      __android_log_unlock();
 
-      if (ret < 0) {
-        return ret;
-      }
-
-      ret = TEMP_FAILURE_RETRY(writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
-      if (ret < 0) {
-        ret = -errno;
-      }
-      [[fallthrough]];
-    default:
-      break;
+  if (ret < 0) {
+    ret = -errno;
   }
 
   if (ret > (ssize_t)sizeof(header)) {
     ret -= sizeof(header);
-  } else if (ret == -EAGAIN) {
+  } else if (ret < 0) {
     atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
     if (logId == LOG_ID_SECURITY) {
       atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed);
diff --git a/liblog/logger.h b/liblog/logger.h
index 1f632c0..40d5fe5 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <stdatomic.h>
-#include <stdbool.h>
 
 #include <cutils/list.h>
 #include <log/log.h>
@@ -27,120 +26,35 @@
 
 __BEGIN_DECLS
 
-/* Union, sock or fd of zero is not allowed unless static initialized */
-union android_log_context_union {
-  void* priv;
-  atomic_int sock;
-  atomic_int fd;
-  struct listnode* node;
-  atomic_uintptr_t atomic_pointer;
-};
-
 struct android_log_transport_write {
-  struct listnode node;
-  const char* name;                  /* human name to describe the transport */
-  unsigned logMask;                  /* mask cache of available() success */
-  union android_log_context_union context; /* Initialized by static allocation */
-
-  int (*available)(log_id_t logId); /* Does not cause resources to be taken */
-  int (*open)();   /* can be called multiple times, reusing current resources */
   void (*close)(); /* free up resources */
   /* write log to transport, returns number of bytes propagated, or -errno */
   int (*write)(log_id_t logId, struct timespec* ts, struct iovec* vec,
                size_t nr);
 };
 
-struct android_log_logger_list;
-struct android_log_transport_context;
-struct android_log_logger;
-
-struct android_log_transport_read {
-  struct listnode node;
-  const char* name; /* human name to describe the transport */
-
-  /* Does not cause resources to be taken */
-  int (*available)(log_id_t logId);
-  int (*version)(struct android_log_logger* logger,
-                 struct android_log_transport_context* transp);
-  /* Release resources taken by the following interfaces */
-  void (*close)(struct android_log_logger_list* logger_list,
-                struct android_log_transport_context* transp);
-  /*
-   * Expect all to instantiate open automagically on any call,
-   * so we do not have an explicit open call.
-   */
-  int (*read)(struct android_log_logger_list* logger_list,
-              struct android_log_transport_context* transp,
-              struct log_msg* log_msg);
-  /* Must only be called if not ANDROID_LOG_NONBLOCK (blocking) */
-  int (*poll)(struct android_log_logger_list* logger_list,
-              struct android_log_transport_context* transp);
-
-  int (*clear)(struct android_log_logger* logger,
-               struct android_log_transport_context* transp);
-  ssize_t (*setSize)(struct android_log_logger* logger,
-                     struct android_log_transport_context* transp, size_t size);
-  ssize_t (*getSize)(struct android_log_logger* logger,
-                     struct android_log_transport_context* transp);
-  ssize_t (*getReadableSize)(struct android_log_logger* logger,
-                             struct android_log_transport_context* transp);
-
-  ssize_t (*getPrune)(struct android_log_logger_list* logger_list,
-                      struct android_log_transport_context* transp, char* buf,
-                      size_t len);
-  ssize_t (*setPrune)(struct android_log_logger_list* logger_list,
-                      struct android_log_transport_context* transp, char* buf,
-                      size_t len);
-  ssize_t (*getStats)(struct android_log_logger_list* logger_list,
-                      struct android_log_transport_context* transp, char* buf,
-                      size_t len);
-};
-
-struct android_log_logger_list {
-  struct listnode logger;
-  struct listnode transport;
+struct logger_list {
+  atomic_int fd;
   int mode;
   unsigned int tail;
   log_time start;
   pid_t pid;
+  uint32_t log_mask;
 };
 
-struct android_log_logger {
-  struct listnode node;
-  struct android_log_logger_list* parent;
+// Format for a 'logger' entry: uintptr_t where only the bottom 32 bits are used.
+// bit 31: Set if this 'logger' is for logd.
+// bit 30: Set if this 'logger' is for pmsg
+// bits 0-2: the decimal value of the log buffer.
+// Other bits are unused.
 
-  log_id_t logId;
-};
+#define LOGGER_LOGD (1U << 31)
+#define LOGGER_PMSG (1U << 30)
+#define LOGGER_LOG_ID_MASK ((1U << 3) - 1)
 
-struct android_log_transport_context {
-  struct listnode node;
-  union android_log_context_union context; /* zero init per-transport context */
-  struct android_log_logger_list* parent;
-
-  struct android_log_transport_read* transport;
-  unsigned logMask;      /* mask of requested log buffers */
-  int ret;               /* return value associated with following data */
-  struct log_msg logMsg; /* peek at upcoming data, valid if logMsg.len != 0 */
-};
-
-/* assumes caller has structures read-locked, single threaded, or fenced */
-#define transport_context_for_each(transp, logger_list)                          \
-  for ((transp) = node_to_item((logger_list)->transport.next,                    \
-                               struct android_log_transport_context, node);      \
-       ((transp) != node_to_item(&(logger_list)->transport,                      \
-                                 struct android_log_transport_context, node)) && \
-       ((transp)->parent == (logger_list));                                      \
-       (transp) = node_to_item((transp)->node.next,                              \
-                               struct android_log_transport_context, node))
-
-#define logger_for_each(logp, logger_list)                          \
-  for ((logp) = node_to_item((logger_list)->logger.next,            \
-                             struct android_log_logger, node);      \
-       ((logp) != node_to_item(&(logger_list)->logger,              \
-                               struct android_log_logger, node)) && \
-       ((logp)->parent == (logger_list));                           \
-       (logp) =                                                     \
-           node_to_item((logp)->node.next, struct android_log_logger, node))
+inline bool android_logger_is_logd(struct logger* logger) {
+  return reinterpret_cast<uintptr_t>(logger) & LOGGER_LOGD;
+}
 
 /* OS specific dribs and drabs */
 
@@ -156,10 +70,4 @@
 }
 #endif
 
-void __android_log_lock();
-int __android_log_trylock();
-void __android_log_unlock();
-
-extern int __android_log_transport;
-
 __END_DECLS
diff --git a/liblog/logger_lock.cpp b/liblog/logger_lock.cpp
deleted file mode 100644
index 4636b00..0000000
--- a/liblog/logger_lock.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2007-2016 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.
- */
-
-/*
- * Some OS specific dribs and drabs (locking etc).
- */
-
-#if !defined(_WIN32)
-#include <pthread.h>
-#endif
-
-#include "logger.h"
-
-#if !defined(_WIN32)
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-void __android_log_lock() {
-#if !defined(_WIN32)
-  /*
-   * If we trigger a signal handler in the middle of locked activity and the
-   * signal handler logs a message, we could get into a deadlock state.
-   */
-  pthread_mutex_lock(&log_init_lock);
-#endif
-}
-
-int __android_log_trylock() {
-#if !defined(_WIN32)
-  return pthread_mutex_trylock(&log_init_lock);
-#else
-  return 0;
-#endif
-}
-
-void __android_log_unlock() {
-#if !defined(_WIN32)
-  pthread_mutex_unlock(&log_init_lock);
-#endif
-}
diff --git a/liblog/logger_read.cpp b/liblog/logger_read.cpp
index 4cf0846..0d383ff 100644
--- a/liblog/logger_read.cpp
+++ b/liblog/logger_read.cpp
@@ -21,6 +21,7 @@
 #include <pthread.h>
 #include <sched.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -29,257 +30,50 @@
 #include <cutils/list.h>
 #include <private/android_filesystem_config.h>
 
-#include "config_read.h"
 #include "log_portability.h"
+#include "logd_reader.h"
 #include "logger.h"
-
-/* android_logger_alloc unimplemented, no use case */
-/* android_logger_free not exported */
-static void android_logger_free(struct logger* logger) {
-  struct android_log_logger* logger_internal = (struct android_log_logger*)logger;
-
-  if (!logger_internal) {
-    return;
-  }
-
-  list_remove(&logger_internal->node);
-
-  free(logger_internal);
-}
-
-/* android_logger_alloc unimplemented, no use case */
+#include "pmsg_reader.h"
 
 /* method for getting the associated sublog id */
 log_id_t android_logger_get_id(struct logger* logger) {
-  return ((struct android_log_logger*)logger)->logId;
+  return static_cast<log_id_t>(reinterpret_cast<uintptr_t>(logger) & LOGGER_LOG_ID_MASK);
 }
 
-static int init_transport_context(struct android_log_logger_list* logger_list) {
-  struct android_log_transport_read* transport;
-  struct listnode* node;
-
+static struct logger_list* android_logger_list_alloc_internal(int mode, unsigned int tail,
+                                                              log_time start, pid_t pid) {
+  auto* logger_list = static_cast<struct logger_list*>(calloc(1, sizeof(struct logger_list)));
   if (!logger_list) {
-    return -EINVAL;
+    return nullptr;
   }
 
-  if (list_empty(&logger_list->logger)) {
-    return -EINVAL;
-  }
-
-  if (!list_empty(&logger_list->transport)) {
-    return 0;
-  }
-
-  __android_log_lock();
-  /* mini __write_to_log_initialize() to populate transports */
-  if (list_empty(&__android_log_transport_read) && list_empty(&__android_log_persist_read)) {
-    __android_log_config_read();
-  }
-  __android_log_unlock();
-
-  node = (logger_list->mode & ANDROID_LOG_PSTORE) ? &__android_log_persist_read
-                                                  : &__android_log_transport_read;
-
-  read_transport_for_each(transport, node) {
-    struct android_log_transport_context* transp;
-    struct android_log_logger* logger;
-    unsigned logMask = 0;
-
-    logger_for_each(logger, logger_list) {
-      log_id_t logId = logger->logId;
-
-      if ((logId == LOG_ID_SECURITY) && (__android_log_uid() != AID_SYSTEM)) {
-        continue;
-      }
-      if (transport->read && (!transport->available || (transport->available(logId) >= 0))) {
-        logMask |= 1 << logId;
-      }
-    }
-    if (!logMask) {
-      continue;
-    }
-    transp = static_cast<android_log_transport_context*>(calloc(1, sizeof(*transp)));
-    if (!transp) {
-      return -ENOMEM;
-    }
-    transp->parent = logger_list;
-    transp->transport = transport;
-    transp->logMask = logMask;
-    transp->ret = 1;
-    list_add_tail(&logger_list->transport, &transp->node);
-  }
-  if (list_empty(&logger_list->transport)) {
-    return -ENODEV;
-  }
-  return 0;
-}
-
-#define LOGGER_FUNCTION(logger, def, func, args...)                                  \
-  ssize_t ret = -EINVAL;                                                             \
-  struct android_log_transport_context* transp;                                      \
-  struct android_log_logger* logger_internal = (struct android_log_logger*)(logger); \
-                                                                                     \
-  if (!logger_internal) {                                                            \
-    return ret;                                                                      \
-  }                                                                                  \
-  ret = init_transport_context(logger_internal->parent);                             \
-  if (ret < 0) {                                                                     \
-    return ret;                                                                      \
-  }                                                                                  \
-                                                                                     \
-  ret = (def);                                                                       \
-  transport_context_for_each(transp, logger_internal->parent) {                      \
-    if ((transp->logMask & (1 << logger_internal->logId)) && transp->transport &&    \
-        transp->transport->func) {                                                   \
-      ssize_t retval = (transp->transport->func)(logger_internal, transp, ##args);   \
-      if ((ret >= 0) || (ret == (def))) {                                            \
-        ret = retval;                                                                \
-      }                                                                              \
-    }                                                                                \
-  }                                                                                  \
-  return ret
-
-int android_logger_clear(struct logger* logger) {
-  LOGGER_FUNCTION(logger, -ENODEV, clear);
-}
-
-/* returns the total size of the log's ring buffer */
-long android_logger_get_log_size(struct logger* logger) {
-  LOGGER_FUNCTION(logger, -ENODEV, getSize);
-}
-
-int android_logger_set_log_size(struct logger* logger, unsigned long size) {
-  LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
-}
-
-/*
- * returns the readable size of the log's ring buffer (that is, amount of the
- * log consumed)
- */
-long android_logger_get_log_readable_size(struct logger* logger) {
-  LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
-}
-
-/*
- * returns the logger version
- */
-int android_logger_get_log_version(struct logger* logger) {
-  LOGGER_FUNCTION(logger, 4, version);
-}
-
-#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...)                           \
-  struct android_log_transport_context* transp;                                         \
-  struct android_log_logger_list* logger_list_internal =                                \
-      (struct android_log_logger_list*)(logger_list);                                   \
-                                                                                        \
-  ssize_t ret = init_transport_context(logger_list_internal);                           \
-  if (ret < 0) {                                                                        \
-    return ret;                                                                         \
-  }                                                                                     \
-                                                                                        \
-  ret = (def);                                                                          \
-  transport_context_for_each(transp, logger_list_internal) {                            \
-    if (transp->transport && (transp->transport->func)) {                               \
-      ssize_t retval = (transp->transport->func)(logger_list_internal, transp, ##args); \
-      if ((ret >= 0) || (ret == (def))) {                                               \
-        ret = retval;                                                                   \
-      }                                                                                 \
-    }                                                                                   \
-  }                                                                                     \
-  return ret
-
-/*
- * returns statistics
- */
-ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf, size_t len) {
-  LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
-}
-
-ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
-  LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
-}
-
-int android_logger_set_prune_list(struct logger_list* logger_list, char* buf, size_t len) {
-  LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
-}
-
-struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
-  struct android_log_logger_list* logger_list;
-
-  logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
-  if (!logger_list) {
-    return NULL;
-  }
-
-  list_init(&logger_list->logger);
-  list_init(&logger_list->transport);
   logger_list->mode = mode;
+  logger_list->start = start;
   logger_list->tail = tail;
   logger_list->pid = pid;
 
-  return (struct logger_list*)logger_list;
+  return logger_list;
+}
+
+struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
+  return android_logger_list_alloc_internal(mode, tail, log_time(0, 0), pid);
 }
 
 struct logger_list* android_logger_list_alloc_time(int mode, log_time start, pid_t pid) {
-  struct android_log_logger_list* logger_list;
-
-  logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
-  if (!logger_list) {
-    return NULL;
-  }
-
-  list_init(&logger_list->logger);
-  list_init(&logger_list->transport);
-  logger_list->mode = mode;
-  logger_list->start = start;
-  logger_list->pid = pid;
-
-  return (struct logger_list*)logger_list;
+  return android_logger_list_alloc_internal(mode, 0, start, pid);
 }
 
-/* android_logger_list_register unimplemented, no use case */
-/* android_logger_list_unregister unimplemented, no use case */
-
 /* Open the named log and add it to the logger list */
 struct logger* android_logger_open(struct logger_list* logger_list, log_id_t logId) {
-  struct android_log_logger_list* logger_list_internal =
-      (struct android_log_logger_list*)logger_list;
-  struct android_log_logger* logger;
-
-  if (!logger_list_internal || (logId >= LOG_ID_MAX)) {
-    goto err;
+  if (!logger_list || (logId >= LOG_ID_MAX)) {
+    return nullptr;
   }
 
-  logger_for_each(logger, logger_list_internal) {
-    if (logger->logId == logId) {
-      goto ok;
-    }
-  }
+  logger_list->log_mask |= 1 << logId;
 
-  logger = static_cast<android_log_logger*>(calloc(1, sizeof(*logger)));
-  if (!logger) {
-    goto err;
-  }
-
-  logger->logId = logId;
-  list_add_tail(&logger_list_internal->logger, &logger->node);
-  logger->parent = logger_list_internal;
-
-  /* Reset known transports to re-evaluate, we just added one */
-  while (!list_empty(&logger_list_internal->transport)) {
-    struct listnode* node = list_head(&logger_list_internal->transport);
-    struct android_log_transport_context* transp =
-        node_to_item(node, struct android_log_transport_context, node);
-
-    list_remove(&transp->node);
-    free(transp);
-  }
-  goto ok;
-
-err:
-  logger = NULL;
-ok:
-  return (struct logger*)logger;
+  uintptr_t logger = logId;
+  logger |= (logger_list->mode & ANDROID_LOG_PSTORE) ? LOGGER_PMSG : LOGGER_LOGD;
+  return reinterpret_cast<struct logger*>(logger);
 }
 
 /* Open the single named log and make it part of a new logger list */
@@ -299,162 +93,58 @@
   return logger_list;
 }
 
-/* Validate log_msg packet, read function has already been null checked */
-static int android_transport_read(struct android_log_logger_list* logger_list,
-                                  struct android_log_transport_context* transp,
-                                  struct log_msg* log_msg) {
-  int ret = (*transp->transport->read)(logger_list, transp, log_msg);
+int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
+  if (logger_list == nullptr || logger_list->log_mask == 0) {
+    return -EINVAL;
+  }
+
+  int ret = 0;
+
+#if (FAKE_LOG_DEVICE == 0)
+  if (logger_list->mode & ANDROID_LOG_PSTORE) {
+    ret = PmsgRead(logger_list, log_msg);
+  } else {
+    ret = LogdRead(logger_list, log_msg);
+  }
+#endif
+
+  if (ret <= 0) {
+    return ret;
+  }
 
   if (ret > (int)sizeof(*log_msg)) {
     ret = sizeof(*log_msg);
   }
 
-  transp->ret = ret;
-
-  /* propagate errors, or make sure len & hdr_size members visible */
-  if (ret < (int)(sizeof(log_msg->entry.len) + sizeof(log_msg->entry.hdr_size))) {
-    if (ret >= (int)sizeof(log_msg->entry.len)) {
-      log_msg->entry.len = 0;
-    }
-    return ret;
-  }
-
-  /* hdr_size correction (logger_entry -> logger_entry_v2+ conversion) */
-  if (log_msg->entry_v2.hdr_size == 0) {
-    log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
-  }
-  if ((log_msg->entry_v2.hdr_size < sizeof(log_msg->entry_v1)) ||
-      (log_msg->entry_v2.hdr_size > sizeof(log_msg->entry))) {
+  if (ret < static_cast<int>(sizeof(log_msg->entry))) {
     return -EINVAL;
   }
 
-  /* len validation */
-  if (ret <= log_msg->entry_v2.hdr_size) {
-    log_msg->entry.len = 0;
-  } else {
-    log_msg->entry.len = ret - log_msg->entry_v2.hdr_size;
+  if (log_msg->entry.hdr_size < sizeof(log_msg->entry) ||
+      log_msg->entry.hdr_size >= sizeof(struct log_msg) - sizeof(log_msg->entry)) {
+    return -EINVAL;
+  }
+
+  if (log_msg->entry.len > ret - log_msg->entry.hdr_size) {
+    return -EINVAL;
   }
 
   return ret;
 }
 
-/* Read from the selected logs */
-int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
-  struct android_log_transport_context* transp;
-  struct android_log_logger_list* logger_list_internal =
-      (struct android_log_logger_list*)logger_list;
-
-  int ret = init_transport_context(logger_list_internal);
-  if (ret < 0) {
-    return ret;
-  }
-
-  /* at least one transport */
-  transp = node_to_item(logger_list_internal->transport.next, struct android_log_transport_context,
-                        node);
-
-  /* more than one transport? */
-  if (transp->node.next != &logger_list_internal->transport) {
-    /* Poll and merge sort the entries if from multiple transports */
-    struct android_log_transport_context* oldest = NULL;
-    int ret;
-    int polled = 0;
-    do {
-      if (polled) {
-        sched_yield();
-      }
-      ret = -1000;
-      polled = 0;
-      do {
-        int retval = transp->ret;
-        if ((retval > 0) && !transp->logMsg.entry.len) {
-          if (!transp->transport->read) {
-            retval = transp->ret = 0;
-          } else if ((logger_list_internal->mode & ANDROID_LOG_NONBLOCK) ||
-                     !transp->transport->poll) {
-            retval = android_transport_read(logger_list_internal, transp, &transp->logMsg);
-          } else {
-            int pollval = (*transp->transport->poll)(logger_list_internal, transp);
-            if (pollval <= 0) {
-              sched_yield();
-              pollval = (*transp->transport->poll)(logger_list_internal, transp);
-            }
-            polled = 1;
-            if (pollval < 0) {
-              if ((pollval == -EINTR) || (pollval == -EAGAIN)) {
-                return -EAGAIN;
-              }
-              retval = transp->ret = pollval;
-            } else if (pollval > 0) {
-              retval = android_transport_read(logger_list_internal, transp, &transp->logMsg);
-            }
-          }
-        }
-        if (ret < retval) {
-          ret = retval;
-        }
-        if ((transp->ret > 0) && transp->logMsg.entry.len &&
-            (!oldest || (oldest->logMsg.entry.sec > transp->logMsg.entry.sec) ||
-             ((oldest->logMsg.entry.sec == transp->logMsg.entry.sec) &&
-              (oldest->logMsg.entry.nsec > transp->logMsg.entry.nsec)))) {
-          oldest = transp;
-        }
-        transp = node_to_item(transp->node.next, struct android_log_transport_context, node);
-      } while (transp != node_to_item(&logger_list_internal->transport,
-                                      struct android_log_transport_context, node));
-      if (!oldest && (logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) {
-        return (ret < 0) ? ret : -EAGAIN;
-      }
-      transp = node_to_item(logger_list_internal->transport.next,
-                            struct android_log_transport_context, node);
-    } while (!oldest && (ret > 0));
-    if (!oldest) {
-      return ret;
-    }
-    // ret is a positive value less than sizeof(struct log_msg)
-    ret = oldest->ret;
-    if (ret < oldest->logMsg.entry.hdr_size) {
-      // zero truncated header fields.
-      memset(
-          log_msg, 0,
-          (oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg) ? sizeof(oldest->logMsg)
-                                                                  : oldest->logMsg.entry.hdr_size));
-    }
-    memcpy(log_msg, &oldest->logMsg, ret);
-    oldest->logMsg.entry.len = 0; /* Mark it as copied */
-    return ret;
-  }
-
-  /* if only one, no need to copy into transport_context and merge-sort */
-  return android_transport_read(logger_list_internal, transp, log_msg);
-}
-
 /* Close all the logs */
 void android_logger_list_free(struct logger_list* logger_list) {
-  struct android_log_logger_list* logger_list_internal =
-      (struct android_log_logger_list*)logger_list;
-
-  if (logger_list_internal == NULL) {
+  if (logger_list == NULL) {
     return;
   }
 
-  while (!list_empty(&logger_list_internal->transport)) {
-    struct listnode* node = list_head(&logger_list_internal->transport);
-    struct android_log_transport_context* transp =
-        node_to_item(node, struct android_log_transport_context, node);
-
-    if (transp->transport && transp->transport->close) {
-      (*transp->transport->close)(logger_list_internal, transp);
-    }
-    list_remove(&transp->node);
-    free(transp);
+#if (FAKE_LOG_DEVICE == 0)
+  if (logger_list->mode & ANDROID_LOG_PSTORE) {
+    PmsgClose(logger_list);
+  } else {
+    LogdClose(logger_list);
   }
+#endif
 
-  while (!list_empty(&logger_list_internal->logger)) {
-    struct listnode* node = list_head(&logger_list_internal->logger);
-    struct android_log_logger* logger = node_to_item(node, struct android_log_logger, node);
-    android_logger_free((struct logger*)logger);
-  }
-
-  free(logger_list_internal);
+  free(logger_list);
 }
diff --git a/liblog/logger_write.cpp b/liblog/logger_write.cpp
index 7fa3f43..d38b402 100644
--- a/liblog/logger_write.cpp
+++ b/liblog/logger_write.cpp
@@ -24,31 +24,30 @@
 #include <android/set_abort_message.h>
 #endif
 
-#include <log/event_tag_map.h>
-#include <log/log_transport.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#include "config_read.h" /* __android_log_config_read_close() definition */
-#include "config_write.h"
 #include "log_portability.h"
 #include "logger.h"
 #include "uio.h"
 
 #define LOG_BUF_SIZE 1024
 
-static int __write_to_log_init(log_id_t, struct iovec* vec, size_t nr);
-static int (*write_to_log)(log_id_t, struct iovec* vec, size_t nr) = __write_to_log_init;
+#if (FAKE_LOG_DEVICE == 0)
+extern struct android_log_transport_write logdLoggerWrite;
+extern struct android_log_transport_write pmsgLoggerWrite;
 
-/*
- * This is used by the C++ code to decide if it should write logs through
- * the C code.  Basically, if /dev/socket/logd is available, we're running in
- * the simulator rather than a desktop tool and want to use the device.
- */
-static enum { kLogUninitialized, kLogNotAvailable, kLogAvailable } g_log_status = kLogUninitialized;
+android_log_transport_write* android_log_write = &logdLoggerWrite;
+android_log_transport_write* android_log_persist_write = &pmsgLoggerWrite;
+#else
+extern android_log_transport_write fakeLoggerWrite;
 
-static int check_log_uid_permissions() {
+android_log_transport_write* android_log_write = &fakeLoggerWrite;
+android_log_transport_write* android_log_persist_write = nullptr;
+#endif
+
 #if defined(__ANDROID__)
+static int check_log_uid_permissions() {
   uid_t uid = __android_log_uid();
 
   /* Matches clientHasLogCredentials() in logd */
@@ -85,171 +84,34 @@
       }
     }
   }
-#endif
   return 0;
 }
-
-static void __android_log_cache_available(struct android_log_transport_write* node) {
-  uint32_t i;
-
-  if (node->logMask) {
-    return;
-  }
-
-  for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
-    if (node->write && (i != LOG_ID_KERNEL) &&
-        ((i != LOG_ID_SECURITY) || (check_log_uid_permissions() == 0)) &&
-        (!node->available || ((*node->available)(static_cast<log_id_t>(i)) >= 0))) {
-      node->logMask |= 1 << i;
-    }
-  }
-}
-
-extern "C" int __android_log_dev_available() {
-  struct android_log_transport_write* node;
-
-  if (list_empty(&__android_log_transport_write)) {
-    return kLogUninitialized;
-  }
-
-  write_transport_for_each(node, &__android_log_transport_write) {
-    __android_log_cache_available(node);
-    if (node->logMask) {
-      return kLogAvailable;
-    }
-  }
-  return kLogNotAvailable;
-}
-
-#if defined(__ANDROID__)
-static atomic_uintptr_t tagMap;
 #endif
 
 /*
  * Release any logger resources. A new log write will immediately re-acquire.
  */
 void __android_log_close() {
-  struct android_log_transport_write* transport;
-#if defined(__ANDROID__)
-  EventTagMap* m;
-#endif
-
-  __android_log_lock();
-
-  write_to_log = __write_to_log_init;
-
-  /*
-   * Threads that are actively writing at this point are not held back
-   * by a lock and are at risk of dropping the messages with a return code
-   * -EBADF. Prefer to return error code than add the overhead of a lock to
-   * each log writing call to guarantee delivery. In addition, anyone
-   * calling this is doing so to release the logging resources and shut down,
-   * for them to do so with outstanding log requests in other threads is a
-   * disengenuous use of this function.
-   */
-
-  write_transport_for_each(transport, &__android_log_persist_write) {
-    if (transport->close) {
-      (*transport->close)();
-    }
+  if (android_log_write != nullptr) {
+    android_log_write->close();
   }
 
-  write_transport_for_each(transport, &__android_log_transport_write) {
-    if (transport->close) {
-      (*transport->close)();
-    }
+  if (android_log_persist_write != nullptr) {
+    android_log_persist_write->close();
   }
 
-  __android_log_config_write_close();
-
-#if defined(__ANDROID__)
-  /*
-   * Additional risk here somewhat mitigated by immediately unlock flushing
-   * the processor cache. The multi-threaded race that we choose to accept,
-   * to minimize locking, is an atomic_load in a writer picking up a value
-   * just prior to entering this routine. There will be an use after free.
-   *
-   * Again, anyone calling this is doing so to release the logging resources
-   * is most probably going to quiesce then shut down; or to restart after
-   * a fork so the risk should be non-existent. For this reason we
-   * choose a mitigation stance for efficiency instead of incuring the cost
-   * of a lock for every log write.
-   */
-  m = (EventTagMap*)atomic_exchange(&tagMap, (uintptr_t)0);
-#endif
-
-  __android_log_unlock();
-
-#if defined(__ANDROID__)
-  if (m != (EventTagMap*)(uintptr_t)-1LL) android_closeEventTagMap(m);
-#endif
 }
 
-/* log_init_lock assumed */
-static int __write_to_log_initialize() {
-  struct android_log_transport_write* transport;
-  struct listnode* n;
-  int i = 0, ret = 0;
-
-  __android_log_config_write();
-  write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
-    __android_log_cache_available(transport);
-    if (!transport->logMask) {
-      list_remove(&transport->node);
-      continue;
-    }
-    if (!transport->open || ((*transport->open)() < 0)) {
-      if (transport->close) {
-        (*transport->close)();
-      }
-      list_remove(&transport->node);
-      continue;
-    }
-    ++ret;
-  }
-  write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
-    __android_log_cache_available(transport);
-    if (!transport->logMask) {
-      list_remove(&transport->node);
-      continue;
-    }
-    if (!transport->open || ((*transport->open)() < 0)) {
-      if (transport->close) {
-        (*transport->close)();
-      }
-      list_remove(&transport->node);
-      continue;
-    }
-    ++i;
-  }
-  if (!ret && !i) {
-    return -ENODEV;
-  }
-
-  return ret;
-}
-
-/*
- * Extract a 4-byte value from a byte stream. le32toh open coded
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-static int __write_to_log_daemon(log_id_t log_id, struct iovec* vec, size_t nr) {
-  struct android_log_transport_write* node;
+static int write_to_log(log_id_t log_id, struct iovec* vec, size_t nr) {
   int ret, save_errno;
   struct timespec ts;
-  size_t len, i;
 
-  for (len = i = 0; i < nr; ++i) {
-    len += vec[i].iov_len;
-  }
-  if (!len) {
+  save_errno = errno;
+
+  if (log_id == LOG_ID_KERNEL) {
     return -EINVAL;
   }
 
-  save_errno = errno;
 #if defined(__ANDROID__)
   clock_gettime(android_log_clockid(), &ts);
 
@@ -270,74 +132,14 @@
       return -EPERM;
     }
   } else if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
-    const char* tag;
-    size_t len;
-    EventTagMap *m, *f;
-
     if (vec[0].iov_len < 4) {
       errno = save_errno;
       return -EINVAL;
     }
-
-    tag = NULL;
-    len = 0;
-    f = NULL;
-    m = (EventTagMap*)atomic_load(&tagMap);
-
-    if (!m) {
-      ret = __android_log_trylock();
-      m = (EventTagMap*)atomic_load(&tagMap); /* trylock flush cache */
-      if (!m) {
-        m = android_openEventTagMap(NULL);
-        if (ret) { /* trylock failed, use local copy, mark for close */
-          f = m;
-        } else {
-          if (!m) { /* One chance to open map file */
-            m = (EventTagMap*)(uintptr_t)-1LL;
-          }
-          atomic_store(&tagMap, (uintptr_t)m);
-        }
-      }
-      if (!ret) { /* trylock succeeded, unlock */
-        __android_log_unlock();
-      }
-    }
-    if (m && (m != (EventTagMap*)(uintptr_t)-1LL)) {
-      tag = android_lookupEventTag_len(m, &len, get4LE(static_cast<uint8_t*>(vec[0].iov_base)));
-    }
-    ret = __android_log_is_loggable_len(ANDROID_LOG_INFO, tag, len, ANDROID_LOG_VERBOSE);
-    if (f) { /* local copy marked for close */
-      android_closeEventTagMap(f);
-    }
-    if (!ret) {
-      errno = save_errno;
-      return -EPERM;
-    }
   } else {
-    /* Validate the incoming tag, tag content can not split across iovec */
-    char prio = ANDROID_LOG_VERBOSE;
-    const char* tag = static_cast<const char*>(vec[0].iov_base);
-    size_t len = vec[0].iov_len;
-    if (!tag) {
-      len = 0;
-    }
-    if (len > 0) {
-      prio = *tag;
-      if (len > 1) {
-        --len;
-        ++tag;
-      } else {
-        len = vec[1].iov_len;
-        tag = ((const char*)vec[1].iov_base);
-        if (!tag) {
-          len = 0;
-        }
-      }
-    }
-    /* tag must be nul terminated */
-    if (tag && strnlen(tag, len) >= len) {
-      tag = NULL;
-    }
+    int prio = *static_cast<int*>(vec[0].iov_base);
+    const char* tag = static_cast<const char*>(vec[1].iov_base);
+    size_t len = vec[1].iov_len;
 
     if (!__android_log_is_loggable_len(prio, tag, len - 1, ANDROID_LOG_VERBOSE)) {
       errno = save_errno;
@@ -355,115 +157,37 @@
 #endif
 
   ret = 0;
-  i = 1 << log_id;
-  write_transport_for_each(node, &__android_log_transport_write) {
-    if (node->logMask & i) {
-      ssize_t retval;
-      retval = (*node->write)(log_id, &ts, vec, nr);
-      if (ret >= 0) {
-        ret = retval;
-      }
+
+  if (android_log_write != nullptr) {
+    ssize_t retval;
+    retval = android_log_write->write(log_id, &ts, vec, nr);
+    if (ret >= 0) {
+      ret = retval;
     }
   }
 
-  write_transport_for_each(node, &__android_log_persist_write) {
-    if (node->logMask & i) {
-      (void)(*node->write)(log_id, &ts, vec, nr);
-    }
+  if (android_log_persist_write != nullptr) {
+    android_log_persist_write->write(log_id, &ts, vec, nr);
   }
 
   errno = save_errno;
   return ret;
 }
 
-static int __write_to_log_init(log_id_t log_id, struct iovec* vec, size_t nr) {
-  int ret, save_errno = errno;
-
-  __android_log_lock();
-
-  if (write_to_log == __write_to_log_init) {
-    ret = __write_to_log_initialize();
-    if (ret < 0) {
-      __android_log_unlock();
-      if (!list_empty(&__android_log_persist_write)) {
-        __write_to_log_daemon(log_id, vec, nr);
-      }
-      errno = save_errno;
-      return ret;
-    }
-
-    write_to_log = __write_to_log_daemon;
-  }
-
-  __android_log_unlock();
-
-  ret = write_to_log(log_id, vec, nr);
-  errno = save_errno;
-  return ret;
-}
-
 int __android_log_write(int prio, const char* tag, const char* msg) {
   return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
 }
 
 int __android_log_buf_write(int bufID, int prio, const char* tag, const char* msg) {
-  struct iovec vec[3];
-  char tmp_tag[32];
-
   if (!tag) tag = "";
 
-  /* XXX: This needs to go! */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wstring-plus-int"
-  if (bufID != LOG_ID_RADIO) {
-    switch (tag[0]) {
-      case 'H':
-        if (strcmp(tag + 1, "HTC_RIL" + 1)) break;
-        goto inform;
-      case 'R':
-        /* Any log tag with "RIL" as the prefix */
-        if (strncmp(tag + 1, "RIL" + 1, strlen("RIL") - 1)) break;
-        goto inform;
-      case 'Q':
-        /* Any log tag with "QC_RIL" as the prefix */
-        if (strncmp(tag + 1, "QC_RIL" + 1, strlen("QC_RIL") - 1)) break;
-        goto inform;
-      case 'I':
-        /* Any log tag with "IMS" as the prefix */
-        if (strncmp(tag + 1, "IMS" + 1, strlen("IMS") - 1)) break;
-        goto inform;
-      case 'A':
-        if (strcmp(tag + 1, "AT" + 1)) break;
-        goto inform;
-      case 'G':
-        if (strcmp(tag + 1, "GSM" + 1)) break;
-        goto inform;
-      case 'S':
-        if (strcmp(tag + 1, "STK" + 1) && strcmp(tag + 1, "SMS" + 1)) break;
-        goto inform;
-      case 'C':
-        if (strcmp(tag + 1, "CDMA" + 1)) break;
-        goto inform;
-      case 'P':
-        if (strcmp(tag + 1, "PHONE" + 1)) break;
-      /* FALLTHRU */
-      inform:
-        bufID = LOG_ID_RADIO;
-        snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
-        tag = tmp_tag;
-        [[fallthrough]];
-      default:
-        break;
-    }
-  }
-#pragma clang diagnostic pop
-
 #if __BIONIC__
   if (prio == ANDROID_LOG_FATAL) {
     android_set_abort_message(msg);
   }
 #endif
 
+  struct iovec vec[3];
   vec[0].iov_base = (unsigned char*)&prio;
   vec[0].iov_len = 1;
   vec[1].iov_base = (void*)tag;
@@ -625,82 +349,3 @@
 
   return write_to_log(LOG_ID_SECURITY, vec, 4);
 }
-
-static int __write_to_log_null(log_id_t log_id, struct iovec* vec, size_t nr) {
-  size_t len, i;
-
-  if ((log_id < LOG_ID_MIN) || (log_id >= LOG_ID_MAX)) {
-    return -EINVAL;
-  }
-
-  for (len = i = 0; i < nr; ++i) {
-    len += vec[i].iov_len;
-  }
-  if (!len) {
-    return -EINVAL;
-  }
-  return len;
-}
-
-/* Following functions need access to our internal write_to_log status */
-
-int __android_log_transport;
-
-int android_set_log_transport(int transport_flag) {
-  int retval;
-
-  if (transport_flag < 0) {
-    return -EINVAL;
-  }
-
-  retval = LOGGER_NULL;
-
-  __android_log_lock();
-
-  if (transport_flag & LOGGER_NULL) {
-    write_to_log = __write_to_log_null;
-
-    __android_log_unlock();
-
-    return retval;
-  }
-
-  __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
-
-  transport_flag &= LOGGER_LOGD | LOGGER_STDERR;
-
-  if (__android_log_transport != transport_flag) {
-    __android_log_transport = transport_flag;
-    __android_log_config_write_close();
-    __android_log_config_read_close();
-
-    write_to_log = __write_to_log_init;
-    /* generically we only expect these two values for write_to_log */
-  } else if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
-    write_to_log = __write_to_log_init;
-  }
-
-  retval = __android_log_transport;
-
-  __android_log_unlock();
-
-  return retval;
-}
-
-int android_get_log_transport() {
-  int ret = LOGGER_DEFAULT;
-
-  __android_log_lock();
-  if (write_to_log == __write_to_log_null) {
-    ret = LOGGER_NULL;
-  } else {
-    __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
-    ret = __android_log_transport;
-    if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
-      ret = -EINVAL;
-    }
-  }
-  __android_log_unlock();
-
-  return ret;
-}
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index bc056cb..4b61828 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -26,17 +26,19 @@
 #ifndef __MINGW32__
 #include <pwd.h>
 #endif
-#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/param.h>
 #include <sys/types.h>
+#include <wchar.h>
 
 #include <cutils/list.h>
+
 #include <log/log.h>
 #include <log/logprint.h>
+#include <private/android_logger.h>
 
 #include "log_portability.h"
 
@@ -291,8 +293,10 @@
   return 1;
 }
 
+#ifndef __MINGW32__
 static const char tz[] = "TZ";
 static const char utc[] = "UTC";
+#endif
 
 /**
  * Returns FORMAT_OFF on invalid string
@@ -528,18 +532,12 @@
 
   int i;
   char* msg = buf->msg;
-  struct logger_entry_v2* buf2 = (struct logger_entry_v2*)buf;
-  if (buf2->hdr_size) {
-    if ((buf2->hdr_size < sizeof(((struct log_msg*)NULL)->entry_v1)) ||
-        (buf2->hdr_size > sizeof(((struct log_msg*)NULL)->entry))) {
-      fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
-      return -1;
-    }
-    msg = ((char*)buf2) + buf2->hdr_size;
-    if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
-      entry->uid = ((struct logger_entry_v4*)buf)->uid;
-    }
+  if (buf->hdr_size != sizeof(struct logger_entry)) {
+    fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
+    return -1;
   }
+  entry->uid = buf->uid;
+
   for (i = 1; i < buf->len; i++) {
     if (msg[i] == '\0') {
       if (msgStart == -1) {
@@ -580,24 +578,6 @@
   return 0;
 }
 
-/*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-/*
- * Extract an 8-byte value from a byte stream.
- */
-static inline uint64_t get8LE(const uint8_t* src) {
-  uint32_t low, high;
-
-  low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-  high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
-  return ((uint64_t)high << 32) | (uint64_t)low;
-}
-
 static bool findChar(const char** cp, size_t* len, int c) {
   while ((*len) && isspace(*(*cp))) {
     ++(*cp);
@@ -651,8 +631,7 @@
 
   if (eventDataLen < 1) return -1;
 
-  type = *eventData++;
-  eventDataLen--;
+  type = *eventData;
 
   cp = NULL;
   len = 0;
@@ -741,22 +720,24 @@
     case EVENT_TYPE_INT:
       /* 32-bit signed int */
       {
-        int32_t ival;
-
-        if (eventDataLen < 4) return -1;
-        ival = get4LE(eventData);
-        eventData += 4;
-        eventDataLen -= 4;
-
-        lval = ival;
+        if (eventDataLen < sizeof(android_event_int_t)) return -1;
+        auto* event_int = reinterpret_cast<const android_event_int_t*>(eventData);
+        lval = event_int->data;
+        eventData += sizeof(android_event_int_t);
+        eventDataLen -= sizeof(android_event_int_t);
       }
       goto pr_lval;
     case EVENT_TYPE_LONG:
       /* 64-bit signed long */
-      if (eventDataLen < 8) return -1;
-      lval = get8LE(eventData);
-      eventData += 8;
-      eventDataLen -= 8;
+      if (eventDataLen < sizeof(android_event_long_t)) {
+        return -1;
+      }
+      {
+        auto* event_long = reinterpret_cast<const android_event_long_t*>(eventData);
+        lval = event_long->data;
+      }
+      eventData += sizeof(android_event_long_t);
+      eventDataLen -= sizeof(android_event_long_t);
     pr_lval:
       outCount = snprintf(outBuf, outBufLen, "%" PRId64, lval);
       if (outCount < outBufLen) {
@@ -770,14 +751,11 @@
     case EVENT_TYPE_FLOAT:
       /* float */
       {
-        uint32_t ival;
-        float fval;
-
-        if (eventDataLen < 4) return -1;
-        ival = get4LE(eventData);
-        fval = *(float*)&ival;
-        eventData += 4;
-        eventDataLen -= 4;
+        if (eventDataLen < sizeof(android_event_float_t)) return -1;
+        auto* event_float = reinterpret_cast<const android_event_float_t*>(eventData);
+        float fval = event_float->data;
+        eventData += sizeof(android_event_int_t);
+        eventDataLen -= sizeof(android_event_int_t);
 
         outCount = snprintf(outBuf, outBufLen, "%f", fval);
         if (outCount < outBufLen) {
@@ -792,12 +770,11 @@
     case EVENT_TYPE_STRING:
       /* UTF-8 chars, not NULL-terminated */
       {
-        unsigned int strLen;
-
-        if (eventDataLen < 4) return -1;
-        strLen = get4LE(eventData);
-        eventData += 4;
-        eventDataLen -= 4;
+        if (eventDataLen < sizeof(android_event_string_t)) return -1;
+        auto* event_string = reinterpret_cast<const android_event_string_t*>(eventData);
+        unsigned int strLen = event_string->length;
+        eventData += sizeof(android_event_string_t);
+        eventDataLen -= sizeof(android_event_string_t);
 
         if (eventDataLen < strLen) {
           result = -1; /* mark truncated */
@@ -830,20 +807,19 @@
     case EVENT_TYPE_LIST:
       /* N items, all different types */
       {
-        unsigned char count;
-        int i;
+        if (eventDataLen < sizeof(android_event_list_t)) return -1;
+        auto* event_list = reinterpret_cast<const android_event_list_t*>(eventData);
 
-        if (eventDataLen < 1) return -1;
-
-        count = *eventData++;
-        eventDataLen--;
+        int8_t count = event_list->element_count;
+        eventData += sizeof(android_event_list_t);
+        eventDataLen -= sizeof(android_event_list_t);
 
         if (outBufLen <= 0) goto no_room;
 
         *outBuf++ = '[';
         outBufLen--;
 
-        for (i = 0; i < count; i++) {
+        for (int i = 0; i < count; i++) {
           result = android_log_printBinaryEvent(&eventData, &eventDataLen, &outBuf, &outBufLen,
                                                 fmtStr, fmtLen);
           if (result != 0) goto bail;
@@ -1011,32 +987,21 @@
   entry->pid = buf->pid;
   entry->tid = buf->tid;
 
-  /*
-   * Pull the tag out, fill in some additional details based on incoming
-   * buffer version (v3 adds lid, v4 adds uid).
-   */
   eventData = (const unsigned char*)buf->msg;
-  struct logger_entry_v2* buf2 = (struct logger_entry_v2*)buf;
-  if (buf2->hdr_size) {
-    if ((buf2->hdr_size < sizeof(((struct log_msg*)NULL)->entry_v1)) ||
-        (buf2->hdr_size > sizeof(((struct log_msg*)NULL)->entry))) {
-      fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
-      return -1;
-    }
-    eventData = ((unsigned char*)buf2) + buf2->hdr_size;
-    if ((buf2->hdr_size >= sizeof(struct logger_entry_v3)) &&
-        (((struct logger_entry_v3*)buf)->lid == LOG_ID_SECURITY)) {
-      entry->priority = ANDROID_LOG_WARN;
-    }
-    if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
-      entry->uid = ((struct logger_entry_v4*)buf)->uid;
-    }
+  if (buf->hdr_size != sizeof(struct logger_entry)) {
+    fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
+    return -1;
   }
+  if (buf->lid == LOG_ID_SECURITY) {
+    entry->priority = ANDROID_LOG_WARN;
+  }
+  entry->uid = buf->uid;
   inCount = buf->len;
-  if (inCount < 4) return -1;
-  tagIndex = get4LE(eventData);
-  eventData += 4;
-  inCount -= 4;
+  if (inCount < sizeof(android_event_header_t)) return -1;
+  auto* event_header = reinterpret_cast<const android_event_header_t*>(eventData);
+  tagIndex = event_header->tag;
+  eventData += sizeof(android_event_header_t);
+  inCount -= sizeof(android_event_header_t);
 
   entry->tagLen = 0;
   entry->tag = NULL;
@@ -1086,9 +1051,6 @@
   if ((result == 1) && fmtStr) {
     /* We overflowed :-(, let's repaint the line w/o format dressings */
     eventData = (const unsigned char*)buf->msg;
-    if (buf2->hdr_size) {
-      eventData = ((unsigned char*)buf2) + buf2->hdr_size;
-    }
     eventData += 4;
     outBuf = messageBuf;
     outRemaining = messageBufLen - 1;
@@ -1134,66 +1096,13 @@
 }
 
 /*
- * One utf8 character at a time
- *
- * Returns the length of the utf8 character in the buffer,
- * or -1 if illegal or truncated
- *
- * Open coded from libutils/Unicode.cpp, borrowed from utf8_length(),
- * can not remove from here because of library circular dependencies.
- * Expect one-day utf8_character_length with the same signature could
- * _also_ be part of libutils/Unicode.cpp if its usefullness needs to
- * propagate globally.
- */
-LIBLOG_WEAK ssize_t utf8_character_length(const char* src, size_t len) {
-  const char* cur = src;
-  const char first_char = *cur++;
-  static const uint32_t kUnicodeMaxCodepoint = 0x0010FFFF;
-  int32_t mask, to_ignore_mask;
-  size_t num_to_read;
-  uint32_t utf32;
-
-  if ((first_char & 0x80) == 0) { /* ASCII */
-    return first_char ? 1 : -1;
-  }
-
-  /*
-   * (UTF-8's character must not be like 10xxxxxx,
-   *  but 110xxxxx, 1110xxxx, ... or 1111110x)
-   */
-  if ((first_char & 0x40) == 0) {
-    return -1;
-  }
-
-  for (utf32 = 1, num_to_read = 1, mask = 0x40, to_ignore_mask = 0x80;
-       num_to_read < 5 && (first_char & mask); num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
-    if (num_to_read > len) {
-      return -1;
-    }
-    if ((*cur & 0xC0) != 0x80) { /* can not be 10xxxxxx? */
-      return -1;
-    }
-    utf32 = (utf32 << 6) + (*cur++ & 0b00111111);
-  }
-  /* "first_char" must be (110xxxxx - 11110xxx) */
-  if (num_to_read >= 5) {
-    return -1;
-  }
-  to_ignore_mask |= mask;
-  utf32 |= ((~to_ignore_mask) & first_char) << (6 * (num_to_read - 1));
-  if (utf32 > kUnicodeMaxCodepoint) {
-    return -1;
-  }
-  return num_to_read;
-}
-
-/*
  * Convert to printable from message to p buffer, return string length. If p is
  * NULL, do not copy, but still return the expected string length.
  */
-static size_t convertPrintable(char* p, const char* message, size_t messageLen) {
+size_t convertPrintable(char* p, const char* message, size_t messageLen) {
   char* begin = p;
   bool print = p != NULL;
+  mbstate_t mb_state = {};
 
   while (messageLen) {
     char buf[6];
@@ -1201,11 +1110,10 @@
     if ((size_t)len > messageLen) {
       len = messageLen;
     }
-    len = utf8_character_length(message, len);
+    len = mbrtowc(nullptr, message, len, &mb_state);
 
     if (len < 0) {
-      snprintf(buf, sizeof(buf), ((messageLen > 1) && isdigit(message[1])) ? "\\%03o" : "\\%o",
-               *message & 0377);
+      snprintf(buf, sizeof(buf), "\\x%02X", static_cast<unsigned char>(*message));
       len = 1;
     } else {
       buf[0] = '\0';
@@ -1225,7 +1133,7 @@
         } else if (*message == '\\') {
           strcpy(buf, "\\\\");
         } else if ((*message < ' ') || (*message & 0x80)) {
-          snprintf(buf, sizeof(buf), "\\%o", *message & 0377);
+          snprintf(buf, sizeof(buf), "\\x%02X", static_cast<unsigned char>(*message));
         }
       }
       if (!buf[0]) {
@@ -1243,6 +1151,7 @@
   return p - begin;
 }
 
+#ifdef __ANDROID__
 static char* readSeconds(char* e, struct timespec* t) {
   unsigned long multiplier;
   char* p;
@@ -1283,7 +1192,6 @@
   return (long long)now->tv_sec * NS_PER_SEC + now->tv_nsec;
 }
 
-#ifdef __ANDROID__
 static void convertMonotonic(struct timespec* result, const AndroidLogEntry* entry) {
   struct listnode* node;
   struct conversionList {
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index ba27fd7..9390fec 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
+#include "pmsg_reader.h"
+
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
@@ -25,125 +26,21 @@
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#include "config_read.h"
 #include "logger.h"
 
-static int pmsgAvailable(log_id_t logId);
-static int pmsgVersion(struct android_log_logger* logger,
-                       struct android_log_transport_context* transp);
-static int pmsgRead(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp, struct log_msg* log_msg);
-static void pmsgClose(struct android_log_logger_list* logger_list,
-                      struct android_log_transport_context* transp);
-static int pmsgClear(struct android_log_logger* logger,
-                     struct android_log_transport_context* transp);
-
-struct android_log_transport_read pmsgLoggerRead = {
-    .node = {&pmsgLoggerRead.node, &pmsgLoggerRead.node},
-    .name = "pmsg",
-    .available = pmsgAvailable,
-    .version = pmsgVersion,
-    .read = pmsgRead,
-    .poll = NULL,
-    .close = pmsgClose,
-    .clear = pmsgClear,
-    .setSize = NULL,
-    .getSize = NULL,
-    .getReadableSize = NULL,
-    .getPrune = NULL,
-    .setPrune = NULL,
-    .getStats = NULL,
-};
-
-static int pmsgAvailable(log_id_t logId) {
-  if (logId > LOG_ID_SECURITY) {
-    return -EINVAL;
-  }
-  if (access("/dev/pmsg0", W_OK) == 0) {
-    return 0;
-  }
-  return -EBADF;
-}
-
-/* Determine the credentials of the caller */
-static bool uid_has_log_permission(uid_t uid) {
-  return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT) || (uid == AID_LOGD);
-}
-
-static uid_t get_best_effective_uid() {
-  uid_t euid;
-  uid_t uid;
-  gid_t gid;
-  ssize_t i;
-  static uid_t last_uid = (uid_t)-1;
-
-  if (last_uid != (uid_t)-1) {
-    return last_uid;
-  }
-  uid = __android_log_uid();
-  if (uid_has_log_permission(uid)) {
-    return last_uid = uid;
-  }
-  euid = geteuid();
-  if (uid_has_log_permission(euid)) {
-    return last_uid = euid;
-  }
-  gid = getgid();
-  if (uid_has_log_permission(gid)) {
-    return last_uid = gid;
-  }
-  gid = getegid();
-  if (uid_has_log_permission(gid)) {
-    return last_uid = gid;
-  }
-  i = getgroups((size_t)0, NULL);
-  if (i > 0) {
-    gid_t list[i];
-
-    getgroups(i, list);
-    while (--i >= 0) {
-      if (uid_has_log_permission(list[i])) {
-        return last_uid = list[i];
-      }
-    }
-  }
-  return last_uid = uid;
-}
-
-static int pmsgClear(struct android_log_logger* logger __unused,
-                     struct android_log_transport_context* transp __unused) {
-  if (uid_has_log_permission(get_best_effective_uid())) {
-    return unlink("/sys/fs/pstore/pmsg-ramoops-0");
-  }
-  errno = EPERM;
-  return -1;
-}
-
-/*
- * returns the logger version
- */
-static int pmsgVersion(struct android_log_logger* logger __unused,
-                       struct android_log_transport_context* transp __unused) {
-  return 4;
-}
-
-static int pmsgRead(struct android_log_logger_list* logger_list,
-                    struct android_log_transport_context* transp, struct log_msg* log_msg) {
+int PmsgRead(struct logger_list* logger_list, struct log_msg* log_msg) {
   ssize_t ret;
   off_t current, next;
-  uid_t uid;
-  struct android_log_logger* logger;
   struct __attribute__((__packed__)) {
     android_pmsg_log_header_t p;
     android_log_header_t l;
     uint8_t prio;
   } buf;
   static uint8_t preread_count;
-  bool is_system;
 
   memset(log_msg, 0, sizeof(*log_msg));
 
-  if (atomic_load(&transp->context.fd) <= 0) {
+  if (atomic_load(&logger_list->fd) <= 0) {
     int i, fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC);
 
     if (fd < 0) {
@@ -156,7 +53,7 @@
         return -errno;
       }
     }
-    i = atomic_exchange(&transp->context.fd, fd);
+    i = atomic_exchange(&logger_list->fd, fd);
     if ((i > 0) && (i != fd)) {
       close(i);
     }
@@ -167,7 +64,7 @@
     int fd;
 
     if (preread_count < sizeof(buf)) {
-      fd = atomic_load(&transp->context.fd);
+      fd = atomic_load(&logger_list->fd);
       if (fd <= 0) {
         return -EBADF;
       }
@@ -193,46 +90,39 @@
     }
     preread_count = 0;
 
-    if ((transp->logMask & (1 << buf.l.id)) &&
+    if ((logger_list->log_mask & (1 << buf.l.id)) &&
         ((!logger_list->start.tv_sec && !logger_list->start.tv_nsec) ||
          ((logger_list->start.tv_sec <= buf.l.realtime.tv_sec) &&
           ((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
            (logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
         (!logger_list->pid || (logger_list->pid == buf.p.pid))) {
-      uid = get_best_effective_uid();
-      is_system = uid_has_log_permission(uid);
-      if (is_system || (uid == buf.p.uid)) {
-        char* msg = is_system ? log_msg->entry_v4.msg : log_msg->entry_v3.msg;
-        *msg = buf.prio;
-        fd = atomic_load(&transp->context.fd);
-        if (fd <= 0) {
-          return -EBADF;
-        }
-        ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
-        if (ret < 0) {
-          return -errno;
-        }
-        if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
-          return -EIO;
-        }
-
-        log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
-        log_msg->entry_v4.hdr_size =
-            is_system ? sizeof(log_msg->entry_v4) : sizeof(log_msg->entry_v3);
-        log_msg->entry_v4.pid = buf.p.pid;
-        log_msg->entry_v4.tid = buf.l.tid;
-        log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
-        log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
-        log_msg->entry_v4.lid = buf.l.id;
-        if (is_system) {
-          log_msg->entry_v4.uid = buf.p.uid;
-        }
-
-        return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
+      char* msg = log_msg->entry.msg;
+      *msg = buf.prio;
+      fd = atomic_load(&logger_list->fd);
+      if (fd <= 0) {
+        return -EBADF;
       }
+      ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
+      if (ret < 0) {
+        return -errno;
+      }
+      if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
+        return -EIO;
+      }
+
+      log_msg->entry.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
+      log_msg->entry.hdr_size = sizeof(log_msg->entry);
+      log_msg->entry.pid = buf.p.pid;
+      log_msg->entry.tid = buf.l.tid;
+      log_msg->entry.sec = buf.l.realtime.tv_sec;
+      log_msg->entry.nsec = buf.l.realtime.tv_nsec;
+      log_msg->entry.lid = buf.l.id;
+      log_msg->entry.uid = buf.p.uid;
+
+      return ret + sizeof(buf.prio) + log_msg->entry.hdr_size;
     }
 
-    fd = atomic_load(&transp->context.fd);
+    fd = atomic_load(&logger_list->fd);
     if (fd <= 0) {
       return -EBADF;
     }
@@ -240,7 +130,7 @@
     if (current < 0) {
       return -errno;
     }
-    fd = atomic_load(&transp->context.fd);
+    fd = atomic_load(&logger_list->fd);
     if (fd <= 0) {
       return -EBADF;
     }
@@ -254,9 +144,8 @@
   }
 }
 
-static void pmsgClose(struct android_log_logger_list* logger_list __unused,
-                      struct android_log_transport_context* transp) {
-  int fd = atomic_exchange(&transp->context.fd, 0);
+void PmsgClose(struct logger_list* logger_list) {
+  int fd = atomic_exchange(&logger_list->fd, 0);
   if (fd > 0) {
     close(fd);
   }
@@ -273,17 +162,10 @@
 ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio, const char* prefix,
                                      __android_log_pmsg_file_read_fn fn, void* arg) {
   ssize_t ret;
-  struct android_log_logger_list logger_list;
-  struct android_log_transport_context transp;
+  struct logger_list logger_list;
   struct content {
     struct listnode node;
-    union {
-      struct logger_entry_v4 entry;
-      struct logger_entry_v4 entry_v4;
-      struct logger_entry_v3 entry_v3;
-      struct logger_entry_v2 entry_v2;
-      struct logger_entry entry_v1;
-    };
+    struct logger_entry entry;
   } * content;
   struct names {
     struct listnode node;
@@ -302,15 +184,14 @@
 
   /* Add just enough clues in logger_list and transp to make API function */
   memset(&logger_list, 0, sizeof(logger_list));
-  memset(&transp, 0, sizeof(transp));
 
   logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
-  transp.logMask = (unsigned)-1;
+  logger_list.log_mask = (unsigned)-1;
   if (logId != LOG_ID_ANY) {
-    transp.logMask = (1 << logId);
+    logger_list.log_mask = (1 << logId);
   }
-  transp.logMask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
-  if (!transp.logMask) {
+  logger_list.log_mask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
+  if (!logger_list.log_mask) {
     return -EINVAL;
   }
 
@@ -335,25 +216,26 @@
   }
 
   /* Read the file content */
-  while (pmsgRead(&logger_list, &transp, &transp.logMsg) > 0) {
+  log_msg log_msg;
+  while (PmsgRead(&logger_list, &log_msg) > 0) {
     const char* cp;
-    size_t hdr_size = transp.logMsg.entry.hdr_size ? transp.logMsg.entry.hdr_size
-                                                   : sizeof(transp.logMsg.entry_v1);
-    char* msg = (char*)&transp.logMsg + hdr_size;
+    size_t hdr_size = log_msg.entry.hdr_size;
+
+    char* msg = (char*)&log_msg + hdr_size;
     const char* split = NULL;
 
-    if ((hdr_size < sizeof(transp.logMsg.entry_v1)) || (hdr_size > sizeof(transp.logMsg.entry))) {
+    if (hdr_size != sizeof(log_msg.entry)) {
       continue;
     }
     /* Check for invalid sequence number */
-    if ((transp.logMsg.entry.nsec % ANDROID_LOG_PMSG_FILE_SEQUENCE) ||
-        ((transp.logMsg.entry.nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
-         ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE)) {
+    if (log_msg.entry.nsec % ANDROID_LOG_PMSG_FILE_SEQUENCE ||
+        (log_msg.entry.nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
+            ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
       continue;
     }
 
     /* Determine if it has <dirbase>:<filebase> format for tag */
-    len = transp.logMsg.entry.len - sizeof(prio);
+    len = log_msg.entry.len - sizeof(prio);
     for (cp = msg + sizeof(prio); *cp && isprint(*cp) && !isspace(*cp) && --len; ++cp) {
       if (*cp == ':') {
         if (split) {
@@ -399,8 +281,8 @@
     /* check if there is an existing entry */
     list_for_each(node, &name_list) {
       names = node_to_item(node, struct names, node);
-      if (!strcmp(names->name, msg + sizeof(prio)) && (names->id == transp.logMsg.entry.lid) &&
-          (names->prio == *msg)) {
+      if (!strcmp(names->name, msg + sizeof(prio)) && names->id == log_msg.entry.lid &&
+          names->prio == *msg) {
         break;
       }
     }
@@ -417,7 +299,7 @@
         break;
       }
       strcpy(names->name, msg + sizeof(prio));
-      names->id = static_cast<log_id_t>(transp.logMsg.entry.lid);
+      names->id = static_cast<log_id_t>(log_msg.entry.lid);
       names->prio = *msg;
       list_init(&names->content);
       /*
@@ -470,7 +352,7 @@
     /* Remove any file fragments that match our sequence number */
     list_for_each_safe(node, n, &names->content) {
       content = node_to_item(node, struct content, node);
-      if (transp.logMsg.entry.nsec == content->entry.nsec) {
+      if (log_msg.entry.nsec == content->entry.nsec) {
         list_remove(&content->node);
         free(content);
       }
@@ -478,22 +360,22 @@
 
     /* Add content */
     content = static_cast<struct content*>(
-        calloc(1, sizeof(content->node) + hdr_size + transp.logMsg.entry.len));
+        calloc(1, sizeof(content->node) + hdr_size + log_msg.entry.len));
     if (!content) {
       ret = -ENOMEM;
       break;
     }
-    memcpy(&content->entry, &transp.logMsg.entry, hdr_size + transp.logMsg.entry.len);
+    memcpy(&content->entry, &log_msg.entry, hdr_size + log_msg.entry.len);
 
     /* Insert in sequence number sorted order, to ease reconstruction */
     list_for_each_reverse(node, &names->content) {
-      if ((node_to_item(node, struct content, node))->entry.nsec < transp.logMsg.entry.nsec) {
+      if ((node_to_item(node, struct content, node))->entry.nsec < log_msg.entry.nsec) {
         break;
       }
     }
     list_add_head(node, &content->node);
   }
-  pmsgClose(&logger_list, &transp);
+  PmsgClose(&logger_list);
 
   /* Progress through all the collected files */
   list_for_each_safe(node, n, &name_list) {
diff --git a/adb/daemon/set_verity_enable_state_service.h b/liblog/pmsg_reader.h
similarity index 67%
rename from adb/daemon/set_verity_enable_state_service.h
rename to liblog/pmsg_reader.h
index c0ed98e..53746d8 100644
--- a/adb/daemon/set_verity_enable_state_service.h
+++ b/liblog/pmsg_reader.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 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.
@@ -16,8 +16,14 @@
 
 #pragma once
 
-#include "adb_unique_fd.h"
+#include <unistd.h>
 
-#if defined(__ANDROID__)
-void set_verity_enabled_state_service(unique_fd fd, bool enable);
-#endif
+#include "log/log_read.h"
+#include "log_portability.h"
+
+__BEGIN_DECLS
+
+int PmsgRead(struct logger_list* logger_list, struct log_msg* log_msg);
+void PmsgClose(struct logger_list* logger_list);
+
+__END_DECLS
diff --git a/liblog/pmsg_writer.cpp b/liblog/pmsg_writer.cpp
index e851100..4f45780 100644
--- a/liblog/pmsg_writer.cpp
+++ b/liblog/pmsg_writer.cpp
@@ -20,82 +20,52 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
 #include <time.h>
 
+#include <shared_mutex>
+
 #include <log/log_properties.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#include "config_write.h"
 #include "log_portability.h"
 #include "logger.h"
+#include "rwlock.h"
 #include "uio.h"
 
-static int pmsgOpen();
-static void pmsgClose();
-static int pmsgAvailable(log_id_t logId);
-static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
+static void PmsgClose();
+static int PmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
 
 struct android_log_transport_write pmsgLoggerWrite = {
-    .node = {&pmsgLoggerWrite.node, &pmsgLoggerWrite.node},
-    .context.fd = -1,
-    .name = "pmsg",
-    .available = pmsgAvailable,
-    .open = pmsgOpen,
-    .close = pmsgClose,
-    .write = pmsgWrite,
+    .close = PmsgClose,
+    .write = PmsgWrite,
 };
 
-static int pmsgOpen() {
-  int fd = atomic_load(&pmsgLoggerWrite.context.fd);
-  if (fd < 0) {
-    int i;
+static int pmsg_fd;
+static RwLock pmsg_fd_lock;
 
-    fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
-    i = atomic_exchange(&pmsgLoggerWrite.context.fd, fd);
-    if ((i >= 0) && (i != fd)) {
-      close(i);
-    }
+static void PmsgOpen() {
+  auto lock = std::unique_lock{pmsg_fd_lock};
+  if (pmsg_fd > 0) {
+    // Someone raced us and opened the socket already.
+    return;
   }
 
-  return fd;
+  pmsg_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
 }
 
-static void pmsgClose() {
-  int fd = atomic_exchange(&pmsgLoggerWrite.context.fd, -1);
-  if (fd >= 0) {
-    close(fd);
+static void PmsgClose() {
+  auto lock = std::unique_lock{pmsg_fd_lock};
+  if (pmsg_fd > 0) {
+    close(pmsg_fd);
   }
+  pmsg_fd = 0;
 }
 
-static int pmsgAvailable(log_id_t logId) {
-  if (logId > LOG_ID_SECURITY) {
-    return -EINVAL;
-  }
-  if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
-    return -EINVAL;
-  }
-  if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
-    if (access("/dev/pmsg0", W_OK) == 0) {
-      return 0;
-    }
-    return -EBADF;
-  }
-  return 1;
-}
-
-/*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
+static int PmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
   static const unsigned headerLength = 2;
   struct iovec newVec[nr + headerLength];
   android_log_header_t header;
@@ -103,17 +73,31 @@
   size_t i, payloadSize;
   ssize_t ret;
 
-  if ((logId == LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
-    if (vec[0].iov_len < 4) {
-      return -EINVAL;
+  if (!__android_log_is_debuggable()) {
+    if (logId != LOG_ID_EVENTS && logId != LOG_ID_SECURITY) {
+      return -1;
     }
 
-    if (SNET_EVENT_LOG_TAG != get4LE(static_cast<uint8_t*>(vec[0].iov_base))) {
-      return -EPERM;
+    if (logId == LOG_ID_EVENTS) {
+      if (vec[0].iov_len < 4) {
+        return -EINVAL;
+      }
+
+      if (SNET_EVENT_LOG_TAG != *static_cast<uint32_t*>(vec[0].iov_base)) {
+        return -EPERM;
+      }
     }
   }
 
-  if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
+  auto lock = std::shared_lock{pmsg_fd_lock};
+
+  if (pmsg_fd <= 0) {
+    lock.unlock();
+    PmsgOpen();
+    lock.lock();
+  }
+
+  if (pmsg_fd <= 0) {
     return -EBADF;
   }
 
@@ -167,7 +151,7 @@
   }
   pmsgHeader.len += payloadSize;
 
-  ret = TEMP_FAILURE_RETRY(writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
+  ret = TEMP_FAILURE_RETRY(writev(pmsg_fd, newVec, i));
   if (ret < 0) {
     ret = errno ? -errno : -ENOTCONN;
   }
@@ -202,7 +186,6 @@
 /* Write a buffer as filename references (tag = <basedir>:<basename>) */
 ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio, const char* filename,
                                       const char* buf, size_t len) {
-  bool weOpened;
   size_t length, packet_len;
   const char* tag;
   char *cp, *slash;
@@ -242,7 +225,6 @@
   vec[1].iov_base = (unsigned char*)tag;
   vec[1].iov_len = length;
 
-  weOpened = false;
   for (ts.tv_nsec = 0, length = len; length; ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
     ssize_t ret;
     size_t transfer;
@@ -263,37 +245,15 @@
     vec[2].iov_base = (unsigned char*)buf;
     vec[2].iov_len = transfer;
 
-    if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
-      if (!weOpened) { /* Impossible for weOpened = true here */
-        __android_log_lock();
-      }
-      weOpened = atomic_load(&pmsgLoggerWrite.context.fd) < 0;
-      if (!weOpened) {
-        __android_log_unlock();
-      } else if (pmsgOpen() < 0) {
-        __android_log_unlock();
-        free(cp);
-        return -EBADF;
-      }
-    }
-
-    ret = pmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
+    ret = PmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));
 
     if (ret <= 0) {
-      if (weOpened) {
-        pmsgClose();
-        __android_log_unlock();
-      }
       free(cp);
       return ret ? ret : (len - length);
     }
     length -= transfer;
     buf += transfer;
   }
-  if (weOpened) {
-    pmsgClose();
-    __android_log_unlock();
-  }
   free(cp);
   return len;
 }
diff --git a/liblog/rwlock.h b/liblog/rwlock.h
new file mode 100644
index 0000000..00f1806
--- /dev/null
+++ b/liblog/rwlock.h
@@ -0,0 +1,39 @@
+/*
+ * 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 <pthread.h>
+
+// As of the end of Dec 2019, std::shared_mutex is *not* simply a pthread_rwlock, but rather a
+// combination of std::mutex and std::condition variable, which is obviously less efficient.  This
+// immitates what std::shared_mutex should be doing and is compatible with std::shared_lock and
+// std::unique_lock.
+
+class RwLock {
+ public:
+  RwLock() {}
+  ~RwLock() {}
+
+  void lock() { pthread_rwlock_wrlock(&rwlock_); }
+  void unlock() { pthread_rwlock_unlock(&rwlock_); }
+
+  void lock_shared() { pthread_rwlock_rdlock(&rwlock_); }
+  void unlock_shared() { pthread_rwlock_unlock(&rwlock_); }
+
+ private:
+  pthread_rwlock_t rwlock_ = PTHREAD_RWLOCK_INITIALIZER;
+};
diff --git a/liblog/stderr_write.cpp b/liblog/stderr_write.cpp
deleted file mode 100644
index e324a7c..0000000
--- a/liblog/stderr_write.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-/*
- * stderr write handler.  Output is logcat-like, and responds to
- * logcat's environment variables ANDROID_PRINTF_LOG and
- * ANDROID_LOG_TAGS to filter output.
- *
- * This transport only provides a writer, that means that it does not
- * provide an End-To-End capability as the logs are effectively _lost_
- * to the stderr file stream.  The purpose of this transport is to
- * supply a means for command line tools to report their logging
- * to the stderr stream, in line with all other activities.
- */
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <log/event_tag_map.h>
-#include <log/log.h>
-#include <log/logprint.h>
-
-#include "log_portability.h"
-#include "logger.h"
-#include "uio.h"
-
-static int stderrOpen();
-static void stderrClose();
-static int stderrAvailable(log_id_t logId);
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
-
-struct stderrContext {
-  AndroidLogFormat* logformat;
-#if defined(__ANDROID__)
-  EventTagMap* eventTagMap;
-#endif
-};
-
-struct android_log_transport_write stderrLoggerWrite = {
-    .node = {&stderrLoggerWrite.node, &stderrLoggerWrite.node},
-    .context.priv = NULL,
-    .name = "stderr",
-    .available = stderrAvailable,
-    .open = stderrOpen,
-    .close = stderrClose,
-    .write = stderrWrite,
-};
-
-static int stderrOpen() {
-  struct stderrContext* ctx;
-  const char* envStr;
-  bool setFormat;
-
-  if (!stderr || (fileno(stderr) < 0)) {
-    return -EBADF;
-  }
-
-  if (stderrLoggerWrite.context.priv) {
-    return fileno(stderr);
-  }
-
-  ctx = static_cast<stderrContext*>(calloc(1, sizeof(stderrContext)));
-  if (!ctx) {
-    return -ENOMEM;
-  }
-
-  ctx->logformat = android_log_format_new();
-  if (!ctx->logformat) {
-    free(ctx);
-    return -ENOMEM;
-  }
-
-  envStr = getenv("ANDROID_PRINTF_LOG");
-  setFormat = false;
-
-  if (envStr) {
-    char* formats = strdup(envStr);
-    char* sv = NULL;
-    char* arg = formats;
-    while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) {
-      AndroidLogPrintFormat format = android_log_formatFromString(arg);
-      arg = NULL;
-      if (format == FORMAT_OFF) {
-        continue;
-      }
-      if (android_log_setPrintFormat(ctx->logformat, format) <= 0) {
-        continue;
-      }
-      setFormat = true;
-    }
-    free(formats);
-  }
-  if (!setFormat) {
-    AndroidLogPrintFormat format = android_log_formatFromString("threadtime");
-    android_log_setPrintFormat(ctx->logformat, format);
-  }
-  envStr = getenv("ANDROID_LOG_TAGS");
-  if (envStr) {
-    android_log_addFilterString(ctx->logformat, envStr);
-  }
-  stderrLoggerWrite.context.priv = ctx;
-
-  return fileno(stderr);
-}
-
-static void stderrClose() {
-  stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
-
-  if (ctx) {
-    stderrLoggerWrite.context.priv = NULL;
-    if (ctx->logformat) {
-      android_log_format_free(ctx->logformat);
-      ctx->logformat = NULL;
-    }
-#if defined(__ANDROID__)
-    if (ctx->eventTagMap) {
-      android_closeEventTagMap(ctx->eventTagMap);
-      ctx->eventTagMap = NULL;
-    }
-#endif
-  }
-}
-
-static int stderrAvailable(log_id_t logId) {
-  if ((logId >= LOG_ID_MAX) || (logId == LOG_ID_KERNEL)) {
-    return -EINVAL;
-  }
-  return 1;
-}
-
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
-  struct log_msg log_msg;
-  AndroidLogEntry entry;
-  char binaryMsgBuf[1024];
-  int err;
-  size_t i;
-  stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
-
-  if (!ctx) return -EBADF;
-  if (!vec || !nr) return -EINVAL;
-
-  log_msg.entry.len = 0;
-  log_msg.entry.hdr_size = sizeof(log_msg.entry);
-  log_msg.entry.pid = getpid();
-#ifdef __BIONIC__
-  log_msg.entry.tid = gettid();
-#else
-  log_msg.entry.tid = getpid();
-#endif
-  log_msg.entry.sec = ts->tv_sec;
-  log_msg.entry.nsec = ts->tv_nsec;
-  log_msg.entry.lid = logId;
-  log_msg.entry.uid = __android_log_uid();
-
-  for (i = 0; i < nr; ++i) {
-    size_t len = vec[i].iov_len;
-    if ((log_msg.entry.len + len) > LOGGER_ENTRY_MAX_PAYLOAD) {
-      len = LOGGER_ENTRY_MAX_PAYLOAD - log_msg.entry.len;
-    }
-    if (!len) continue;
-    memcpy(log_msg.entry.msg + log_msg.entry.len, vec[i].iov_base, len);
-    log_msg.entry.len += len;
-  }
-
-  if ((logId == LOG_ID_EVENTS) || (logId == LOG_ID_SECURITY)) {
-#if defined(__ANDROID__)
-    if (!ctx->eventTagMap) {
-      ctx->eventTagMap = android_openEventTagMap(NULL);
-    }
-#endif
-    err = android_log_processBinaryLogBuffer(&log_msg.entry_v1, &entry,
-#if defined(__ANDROID__)
-                                             ctx->eventTagMap,
-#else
-                                             NULL,
-#endif
-                                             binaryMsgBuf, sizeof(binaryMsgBuf));
-  } else {
-    err = android_log_processLogBuffer(&log_msg.entry_v1, &entry);
-  }
-
-  /* print known truncated data, in essence logcat --debug */
-  if ((err < 0) && !entry.message) return -EINVAL;
-
-  if (!android_log_shouldPrintLine(ctx->logformat, entry.tag, entry.priority)) {
-    return log_msg.entry.len;
-  }
-
-  err = android_log_printLogLine(ctx->logformat, fileno(stderr), &entry);
-  if (err < 0) return errno ? -errno : -EINVAL;
-  return log_msg.entry.len;
-}
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 50755ce..f58c524 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -54,20 +54,22 @@
     ],
     srcs: [
         "libc_test.cpp",
-        "liblog_test_default.cpp",
-        "liblog_test_stderr.cpp",
+        "liblog_test.cpp",
         "log_id_test.cpp",
         "log_radio_test.cpp",
         "log_read_test.cpp",
         "log_system_test.cpp",
         "log_time_test.cpp",
         "log_wrap_test.cpp",
+        "logprint_test.cpp",
+        "rwlock_test.cpp",
     ],
     shared_libs: [
         "libcutils",
         "libbase",
     ],
     static_libs: ["liblog"],
+    isolated: true,
 }
 
 // Build tests for the device (with .so). Run with:
@@ -95,3 +97,11 @@
         "vts",
     ],
 }
+
+cc_test_host {
+    name: "liblog-host-test",
+    static_libs: ["liblog"],
+    shared_libs: ["libbase"],
+    srcs: ["liblog_host_test.cpp"],
+    isolated: true,
+}
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 7d11ccf..39ac7a5 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -17,7 +17,7 @@
 #include <fcntl.h>
 #include <inttypes.h>
 #include <poll.h>
-#include <sys/endian.h>
+#include <sched.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
@@ -30,7 +30,6 @@
 #include <benchmark/benchmark.h>
 #include <cutils/sockets.h>
 #include <log/event_tag_map.h>
-#include <log/log_transport.h>
 #include <private/android_logger.h>
 
 BENCHMARK_MAIN();
@@ -56,8 +55,8 @@
  */
 static void BM_log_maximum_retry(benchmark::State& state) {
   while (state.KeepRunning()) {
-    LOG_FAILURE_RETRY(__android_log_print(
-        ANDROID_LOG_INFO, "BM_log_maximum_retry", "%zu", state.iterations()));
+    LOG_FAILURE_RETRY(__android_log_print(ANDROID_LOG_INFO, "BM_log_maximum_retry", "%" PRIu64,
+                                          state.iterations()));
   }
 }
 BENCHMARK(BM_log_maximum_retry);
@@ -69,27 +68,11 @@
  */
 static void BM_log_maximum(benchmark::State& state) {
   while (state.KeepRunning()) {
-    __android_log_print(ANDROID_LOG_INFO, "BM_log_maximum", "%zu",
-                        state.iterations());
+    __android_log_print(ANDROID_LOG_INFO, "BM_log_maximum", "%" PRIu64, state.iterations());
   }
 }
 BENCHMARK(BM_log_maximum);
 
-static void set_log_null() {
-  android_set_log_transport(LOGGER_NULL);
-}
-
-static void set_log_default() {
-  android_set_log_transport(LOGGER_DEFAULT);
-}
-
-static void BM_log_maximum_null(benchmark::State& state) {
-  set_log_null();
-  BM_log_maximum(state);
-  set_log_default();
-}
-BENCHMARK(BM_log_maximum_null);
-
 /*
  *	Measure the time it takes to collect the time using
  * discrete acquisition (state.PauseTiming() to state.ResumeTiming())
@@ -228,14 +211,14 @@
   buffer.header.tag = 0;
   buffer.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer.payload.data = htole32(snapshot);
+  buffer.payload.data = snapshot;
 
   newVec[2].iov_base = &buffer;
   newVec[2].iov_len = sizeof(buffer);
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer.payload.data = htole32(snapshot);
+    buffer.payload.data = snapshot;
     writev(pstore_fd, newVec, nr);
   }
   state.PauseTiming();
@@ -286,7 +269,7 @@
   memset(buf, 0, sizeof(buf));
   struct packet* buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
   if (((uintptr_t)&buffer->pmsg_header) & 7) {
-    fprintf(stderr, "&buffer=0x%p iterations=%zu\n", &buffer->pmsg_header,
+    fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
             state.iterations());
   }
 
@@ -304,11 +287,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header,
           sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t) +
               sizeof(android_log_event_int_t));
@@ -361,7 +344,7 @@
   memset(buf, 0, sizeof(buf));
   struct packet* buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
   if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
-    fprintf(stderr, "&buffer=0x%p iterations=%zu\n", &buffer->pmsg_header,
+    fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
             state.iterations());
   }
 
@@ -379,11 +362,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header,
           sizeof(android_pmsg_log_header_t) + sizeof(android_log_header_t) +
               sizeof(android_log_event_int_t));
@@ -436,7 +419,7 @@
   memset(buf, 0, sizeof(buf));
   struct packet* buffer = (struct packet*)(((uintptr_t)buf + 7) & ~7);
   if (((uintptr_t)&buffer->pmsg_header) & 7) {
-    fprintf(stderr, "&buffer=0x%p iterations=%zu\n", &buffer->pmsg_header,
+    fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
             state.iterations());
   }
 
@@ -454,11 +437,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
   }
   state.PauseTiming();
@@ -509,7 +492,7 @@
   memset(buf, 0, sizeof(buf));
   struct packet* buffer = (struct packet*)((((uintptr_t)buf + 7) & ~7) + 1);
   if ((((uintptr_t)&buffer->pmsg_header) & 7) != 1) {
-    fprintf(stderr, "&buffer=0x%p iterations=%zu\n", &buffer->pmsg_header,
+    fprintf(stderr, "&buffer=0x%p iterations=%" PRIu64 "\n", &buffer->pmsg_header,
             state.iterations());
   }
 
@@ -527,11 +510,11 @@
   buffer->payload.header.tag = 0;
   buffer->payload.payload.type = EVENT_TYPE_INT;
   uint32_t snapshot = 0;
-  buffer->payload.payload.data = htole32(snapshot);
+  buffer->payload.payload.data = snapshot;
 
   while (state.KeepRunning()) {
     ++snapshot;
-    buffer->payload.payload.data = htole32(snapshot);
+    buffer->payload.payload.data = snapshot;
     write(pstore_fd, &buffer->pmsg_header, LOGGER_ENTRY_MAX_PAYLOAD);
   }
   state.PauseTiming();
@@ -560,7 +543,7 @@
 /* performance test */
 static void BM_sprintf_overhead(benchmark::State& state) {
   while (state.KeepRunning()) {
-    test_print("BM_sprintf_overhead:%zu", state.iterations());
+    test_print("BM_sprintf_overhead:%" PRIu64, state.iterations());
     state.PauseTiming();
     logd_yield();
     state.ResumeTiming();
@@ -575,8 +558,7 @@
  */
 static void BM_log_print_overhead(benchmark::State& state) {
   while (state.KeepRunning()) {
-    __android_log_print(ANDROID_LOG_INFO, "BM_log_overhead", "%zu",
-                        state.iterations());
+    __android_log_print(ANDROID_LOG_INFO, "BM_log_overhead", "%" PRIu64, state.iterations());
     state.PauseTiming();
     logd_yield();
     state.ResumeTiming();
@@ -621,13 +603,6 @@
 }
 BENCHMARK(BM_log_event_overhead_42);
 
-static void BM_log_event_overhead_null(benchmark::State& state) {
-  set_log_null();
-  BM_log_event_overhead(state);
-  set_log_default();
-}
-BENCHMARK(BM_log_event_overhead_null);
-
 /*
  *	Measure the time it takes to submit the android event logging call
  * using discrete acquisition under very-light load (<1% CPU utilization).
@@ -642,15 +617,6 @@
 }
 BENCHMARK(BM_log_light_overhead);
 
-static void BM_log_light_overhead_null(benchmark::State& state) {
-  set_log_null();
-  BM_log_light_overhead(state);
-  set_log_default();
-}
-// Default gets out of hand for this test, so we set a reasonable number of
-// iterations for a timely result.
-BENCHMARK(BM_log_light_overhead_null)->Iterations(500);
-
 static void caught_latency(int /*signum*/) {
   unsigned long long v = 0xDEADBEEFA55A5AA5ULL;
 
@@ -947,7 +913,7 @@
 }
 BENCHMARK(BM_lookupEventTagNum);
 
-// Must be functionally identical to liblog internal __send_log_msg.
+// Must be functionally identical to liblog internal SendLogdControlMessage()
 static void send_to_control(char* buf, size_t len) {
   int sock =
       socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM | SOCK_CLOEXEC);
diff --git a/liblog/tests/liblog_host_test.cpp b/liblog/tests/liblog_host_test.cpp
new file mode 100644
index 0000000..377550f
--- /dev/null
+++ b/liblog/tests/liblog_host_test.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 <log/log.h>
+#include <private/android_logger.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/test_utils.h>
+#include <gtest/gtest.h>
+
+using android::base::StringPrintf;
+using android::base::StringReplace;
+
+void GenerateLogContent() {
+  __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_VERBOSE, "tag", "verbose main");
+  __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO, "tag", "info main");
+  __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_ERROR, "tag", "error main");
+
+  __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_VERBOSE, "tag", "verbose radio");
+  __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_INFO, "tag", "info radio");
+  __android_log_buf_print(LOG_ID_RADIO, ANDROID_LOG_ERROR, "tag", "error radio");
+
+  __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, "tag", "verbose system");
+  __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, "tag", "info system");
+  __android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, "tag", "error system");
+
+  __android_log_buf_print(LOG_ID_CRASH, ANDROID_LOG_VERBOSE, "tag", "verbose crash");
+  __android_log_buf_print(LOG_ID_CRASH, ANDROID_LOG_INFO, "tag", "info crash");
+  __android_log_buf_print(LOG_ID_CRASH, ANDROID_LOG_ERROR, "tag", "error crash");
+}
+
+std::string GetPidString() {
+  int pid = getpid();
+  return StringPrintf("%5d", pid);
+}
+
+TEST(liblog, default_write) {
+  setenv("ANDROID_PRINTF_LOG", "brief", true);
+  CapturedStderr captured_stderr;
+
+  GenerateLogContent();
+
+  std::string expected_output = StringReplace(R"init(I/tag     (<pid>): info main
+E/tag     (<pid>): error main
+I/tag     (<pid>): info radio
+E/tag     (<pid>): error radio
+I/tag     (<pid>): info system
+E/tag     (<pid>): error system
+I/tag     (<pid>): info crash
+E/tag     (<pid>): error crash
+)init",
+                                              "<pid>", GetPidString(), true);
+
+  EXPECT_EQ(expected_output, captured_stderr.str());
+}
+
+TEST(liblog, format) {
+  setenv("ANDROID_PRINTF_LOG", "process", true);
+  CapturedStderr captured_stderr;
+
+  GenerateLogContent();
+
+  std::string expected_output = StringReplace(R"init(I(<pid>) info main  (tag)
+E(<pid>) error main  (tag)
+I(<pid>) info radio  (tag)
+E(<pid>) error radio  (tag)
+I(<pid>) info system  (tag)
+E(<pid>) error system  (tag)
+I(<pid>) info crash  (tag)
+E(<pid>) error crash  (tag)
+)init",
+                                              "<pid>", GetPidString(), true);
+
+  EXPECT_EQ(expected_output, captured_stderr.str());
+  captured_stderr.Stop();
+  captured_stderr.Reset();
+  captured_stderr.Start();
+
+  // Changing the environment after starting writing doesn't change the format.
+  setenv("ANDROID_PRINTF_LOG", "brief", true);
+  GenerateLogContent();
+  EXPECT_EQ(expected_output, captured_stderr.str());
+  captured_stderr.Stop();
+  captured_stderr.Reset();
+  captured_stderr.Start();
+
+  // However calling __android_log_close() does reset logging and allow changing the format.
+  __android_log_close();
+  GenerateLogContent();
+
+  expected_output = StringReplace(R"init(I/tag     (<pid>): info main
+E/tag     (<pid>): error main
+I/tag     (<pid>): info radio
+E/tag     (<pid>): error radio
+I/tag     (<pid>): info system
+E/tag     (<pid>): error system
+I/tag     (<pid>): info crash
+E/tag     (<pid>): error crash
+)init",
+                                  "<pid>", GetPidString(), true);
+
+  EXPECT_EQ(expected_output, captured_stderr.str());
+}
+
+TEST(liblog, filter) {
+  setenv("ANDROID_PRINTF_LOG", "brief", true);
+  setenv("ANDROID_LOG_TAGS", "*:w verbose_tag:v debug_tag:d", true);
+  CapturedStderr captured_stderr;
+
+  auto generate_logs = [](log_id_t log_id) {
+    // Check that we show verbose logs when requesting for a given tag.
+    __android_log_buf_print(log_id, ANDROID_LOG_VERBOSE, "verbose_tag", "verbose verbose_tag");
+    __android_log_buf_print(log_id, ANDROID_LOG_ERROR, "verbose_tag", "error verbose_tag");
+
+    // Check that we don't show verbose logs when explicitly requesting debug+ for a given tag.
+    __android_log_buf_print(log_id, ANDROID_LOG_VERBOSE, "debug_tag", "verbose debug_tag");
+    __android_log_buf_print(log_id, ANDROID_LOG_DEBUG, "debug_tag", "debug debug_tag");
+    __android_log_buf_print(log_id, ANDROID_LOG_ERROR, "debug_tag", "error debug_tag");
+
+    // Check that we don't show info logs when requesting globally warn+.
+    __android_log_buf_print(log_id, ANDROID_LOG_INFO, "default_tag", "info default_tag");
+    __android_log_buf_print(log_id, ANDROID_LOG_WARN, "default_tag", "warn default_tag");
+    __android_log_buf_print(log_id, ANDROID_LOG_ERROR, "default_tag", "error default_tag");
+  };
+
+  auto expected_output = StringReplace(R"init(V/verbose_tag(<pid>): verbose verbose_tag
+E/verbose_tag(<pid>): error verbose_tag
+D/debug_tag(<pid>): debug debug_tag
+E/debug_tag(<pid>): error debug_tag
+W/default_tag(<pid>): warn default_tag
+E/default_tag(<pid>): error default_tag
+)init",
+                                       "<pid>", GetPidString(), true);
+
+  auto test_all_logs = [&] {
+    for (auto log_id : {LOG_ID_MAIN, LOG_ID_SYSTEM, LOG_ID_RADIO, LOG_ID_CRASH}) {
+      generate_logs(log_id);
+      EXPECT_EQ(expected_output, captured_stderr.str());
+      captured_stderr.Stop();
+      captured_stderr.Reset();
+      captured_stderr.Start();
+    }
+  };
+
+  test_all_logs();
+
+  // Changing the environment after starting writing doesn't change the filter.
+  setenv("ANDROID_LOG_TAGS", "*:e", true);
+  test_all_logs();
+
+  // However calling __android_log_close() does reset logging and allow changing the format.
+  __android_log_close();
+  expected_output = StringReplace(R"init(E/verbose_tag(<pid>): error verbose_tag
+E/debug_tag(<pid>): error debug_tag
+E/default_tag(<pid>): error default_tag
+)init",
+                                  "<pid>", GetPidString(), true);
+  test_all_logs();
+}
+
+TEST(liblog, kernel_no_write) {
+  CapturedStderr captured_stderr;
+  __android_log_buf_print(LOG_ID_KERNEL, ANDROID_LOG_ERROR, "tag", "kernel error");
+  EXPECT_EQ("", captured_stderr.str());
+}
+
+TEST(liblog, binary_no_write) {
+  CapturedStderr captured_stderr;
+  __android_log_buf_print(LOG_ID_EVENTS, ANDROID_LOG_ERROR, "tag", "error events");
+  __android_log_buf_print(LOG_ID_STATS, ANDROID_LOG_ERROR, "tag", "error stats");
+  __android_log_buf_print(LOG_ID_SECURITY, ANDROID_LOG_ERROR, "tag", "error security");
+
+  __android_log_bswrite(0x12, "events");
+  __android_log_stats_bwrite(0x34, "stats", strlen("stats"));
+  __android_log_security_bswrite(0x56, "security");
+
+  EXPECT_EQ("", captured_stderr.str());
+}
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 1f87b3e..c402e20 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -27,10 +27,12 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <memory>
 #include <string>
 
 #include <android-base/file.h>
 #include <android-base/macros.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #ifdef __ANDROID__  // includes sys/properties.h which does not exist outside
 #include <cutils/properties.h>
@@ -38,25 +40,13 @@
 #include <gtest/gtest.h>
 #include <log/log_event_list.h>
 #include <log/log_properties.h>
-#include <log/log_transport.h>
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
-#ifndef TEST_PREFIX
-#ifdef TEST_LOGGER
-#define TEST_PREFIX android_set_log_transport(TEST_LOGGER);
-// make sure we always run code despite overrides if compiled for android
-#elif defined(__ANDROID__)
-#define TEST_PREFIX
-#endif
-#endif
+using android::base::make_scope_guard;
 
-#ifdef USING_LOGGER_STDERR
-#define SUPPORTS_END_TO_END 0
-#else
-#define SUPPORTS_END_TO_END 1
-#endif
+// #define ENABLE_FLAKY_TESTS
 
 // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
 // non-syscall libs. Since we are only using this in the emergency of
@@ -72,24 +62,93 @@
     _rc;                                                                 \
   })
 
+// std::unique_ptr doesn't let you provide a pointer to a deleter (android_logger_list_close()) if
+// the type (struct logger_list) is an incomplete type, so we create ListCloser instead.
+struct ListCloser {
+  void operator()(struct logger_list* list) { android_logger_list_close(list); }
+};
+
+// This function is meant to be used for most log tests, it does the following:
+// 1) Open the log_buffer with a blocking reader
+// 2) Write the messages via write_messages
+// 3) Set an alarm for 2 seconds as a timeout
+// 4) Read until check_message returns true, which should be used to indicate the target message
+//    is found
+// 5) Open log_buffer with a non_blocking reader and dump all messages
+// 6) Count the number of times check_messages returns true for these messages and assert it's
+//    only 1.
+template <typename FWrite, typename FCheck>
+static void RunLogTests(log_id_t log_buffer, FWrite write_messages, FCheck check_message) {
+  pid_t pid = getpid();
+
+  auto logger_list = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY, 1000, pid)};
+  ASSERT_TRUE(logger_list);
+
+  write_messages();
+
+  alarm(2);
+  auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
+  bool found = false;
+  while (!found) {
+    log_msg log_msg;
+    ASSERT_GT(android_logger_list_read(logger_list.get(), &log_msg), 0);
+
+    ASSERT_EQ(log_buffer, log_msg.id());
+    ASSERT_EQ(pid, log_msg.entry.pid);
+
+    // TODO: Should this be an assert?
+    if (log_msg.msg() == nullptr) {
+      continue;
+    }
+
+    check_message(log_msg, &found);
+  }
+
+  auto logger_list_non_block = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)};
+  ASSERT_TRUE(logger_list_non_block);
+
+  size_t count = 0;
+  while (true) {
+    log_msg log_msg;
+    auto ret = android_logger_list_read(logger_list_non_block.get(), &log_msg);
+    if (ret == -EAGAIN) {
+      break;
+    }
+    ASSERT_GT(ret, 0);
+
+    ASSERT_EQ(log_buffer, log_msg.id());
+    ASSERT_EQ(pid, log_msg.entry.pid);
+
+    // TODO: Should this be an assert?
+    if (log_msg.msg() == nullptr) {
+      continue;
+    }
+
+    found = false;
+    check_message(log_msg, &found);
+    if (found) {
+      ++count;
+    }
+  }
+
+  EXPECT_EQ(1U, count);
+}
+
 TEST(liblog, __android_log_btwrite) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-#endif
   int intBuf = 0xDEADBEEF;
   EXPECT_LT(0,
             __android_log_btwrite(0, EVENT_TYPE_INT, &intBuf, sizeof(intBuf)));
   long long longBuf = 0xDEADBEEFA55A5AA5;
   EXPECT_LT(
       0, __android_log_btwrite(0, EVENT_TYPE_LONG, &longBuf, sizeof(longBuf)));
-  usleep(1000);
   char Buf[] = "\20\0\0\0DeAdBeEfA55a5aA5";
   EXPECT_LT(0,
             __android_log_btwrite(0, EVENT_TYPE_STRING, Buf, sizeof(Buf) - 1));
-  usleep(1000);
 }
 
-#if (defined(__ANDROID__) && defined(USING_LOGGER_DEFAULT))
+#if defined(__ANDROID__)
 static std::string popenToString(const std::string& command) {
   std::string ret;
 
@@ -160,80 +219,60 @@
 
 TEST(liblog, __android_log_btwrite__android_logger_list_read) {
 #ifdef __ANDROID__
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-#endif
-  struct logger_list* logger_list;
-
-  pid_t pid = getpid();
-
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
   log_time ts(CLOCK_MONOTONIC);
-  EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-#ifdef USING_LOGGER_DEFAULT
-  // Check that we can close and reopen the logger
-  bool logdwActiveAfter__android_log_btwrite;
-  if (getuid() == AID_ROOT) {
-    tested__android_log_close = true;
-#ifndef NO_PSTORE
-    bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
-    EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
-#endif /* NO_PSTORE */
-    logdwActiveAfter__android_log_btwrite = isLogdwActive();
-    EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
-  } else if (!tested__android_log_close) {
-    fprintf(stderr, "WARNING: can not test __android_log_close()\n");
-  }
-  __android_log_close();
-  if (getuid() == AID_ROOT) {
-#ifndef NO_PSTORE
-    bool pmsgActiveAfter__android_log_close = isPmsgActive();
-    EXPECT_FALSE(pmsgActiveAfter__android_log_close);
-#endif /* NO_PSTORE */
-    bool logdwActiveAfter__android_log_close = isLogdwActive();
-    EXPECT_FALSE(logdwActiveAfter__android_log_close);
-  }
-#endif
+  log_time ts1(ts);
 
-  log_time ts1(CLOCK_MONOTONIC);
-  EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
-#ifdef USING_LOGGER_DEFAULT
-  if (getuid() == AID_ROOT) {
+  auto write_function = [&] {
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+    // Check that we can close and reopen the logger
+    bool logdwActiveAfter__android_log_btwrite;
+    if (getuid() == AID_ROOT) {
+      tested__android_log_close = true;
 #ifndef NO_PSTORE
-    bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
-    EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+      bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+      EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
 #endif /* NO_PSTORE */
-    logdwActiveAfter__android_log_btwrite = isLogdwActive();
-    EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
-  }
-#endif
-  usleep(1000000);
+      logdwActiveAfter__android_log_btwrite = isLogdwActive();
+      EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
+    } else if (!tested__android_log_close) {
+      fprintf(stderr, "WARNING: can not test __android_log_close()\n");
+    }
+    __android_log_close();
+    if (getuid() == AID_ROOT) {
+#ifndef NO_PSTORE
+      bool pmsgActiveAfter__android_log_close = isPmsgActive();
+      EXPECT_FALSE(pmsgActiveAfter__android_log_close);
+#endif /* NO_PSTORE */
+      bool logdwActiveAfter__android_log_close = isLogdwActive();
+      EXPECT_FALSE(logdwActiveAfter__android_log_close);
+    }
+
+    ts1 = log_time(CLOCK_MONOTONIC);
+    EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
+    if (getuid() == AID_ROOT) {
+#ifndef NO_PSTORE
+      bool pmsgActiveAfter__android_log_btwrite = isPmsgActive();
+      EXPECT_TRUE(pmsgActiveAfter__android_log_btwrite);
+#endif /* NO_PSTORE */
+      logdwActiveAfter__android_log_btwrite = isLogdwActive();
+      EXPECT_TRUE(logdwActiveAfter__android_log_btwrite);
+    }
+  };
 
   int count = 0;
   int second_count = 0;
 
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-
+  auto check_function = [&](log_msg log_msg, bool* found) {
     if ((log_msg.entry.len != sizeof(android_log_event_long_t)) ||
         (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+      return;
     }
 
     android_log_event_long_t* eventData;
     eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
 
     if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
-      continue;
+      return;
     }
 
     log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
@@ -242,171 +281,61 @@
     } else if (ts1 == tx) {
       ++second_count;
     }
-  }
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, second_count);
+    if (count == 1 && second_count == 1) {
+      count = 0;
+      second_count = 0;
+      *found = true;
+    }
+  };
 
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
+
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
+TEST(liblog, __android_log_write__android_logger_list_read) {
 #ifdef __ANDROID__
-static void print_transport(const char* prefix, int logger) {
-  static const char orstr[] = " | ";
-
-  if (!prefix) {
-    prefix = "";
-  }
-  if (logger < 0) {
-    fprintf(stderr, "%s%s\n", prefix, strerror(-logger));
-    return;
-  }
-
-  if (logger == LOGGER_DEFAULT) {
-    fprintf(stderr, "%sLOGGER_DEFAULT", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_LOGD) {
-    fprintf(stderr, "%sLOGGER_LOGD", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_KERNEL) {
-    fprintf(stderr, "%sLOGGER_KERNEL", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_NULL) {
-    fprintf(stderr, "%sLOGGER_NULL", prefix);
-    prefix = orstr;
-  }
-  if (logger & LOGGER_STDERR) {
-    fprintf(stderr, "%sLOGGER_STDERR", prefix);
-    prefix = orstr;
-  }
-  logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_STDERR);
-  if (logger) {
-    fprintf(stderr, "%s0x%x", prefix, logger);
-    prefix = orstr;
-  }
-  if (prefix == orstr) {
-    fprintf(stderr, "\n");
-  }
-}
-#endif
-
-// This test makes little sense standalone, and requires the tests ahead
-// and behind us, to make us whole.  We could incorporate a prefix and
-// suffix test to make this standalone, but opted to not complicate this.
-TEST(liblog, android_set_log_transport) {
-#ifdef __ANDROID__
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-#endif
-
-  int logger = android_get_log_transport();
-  print_transport("android_get_log_transport = ", logger);
-  EXPECT_NE(LOGGER_NULL, logger);
-
-  int ret;
-  EXPECT_EQ(LOGGER_NULL, ret = android_set_log_transport(LOGGER_NULL));
-  print_transport("android_set_log_transport = ", ret);
-  EXPECT_EQ(LOGGER_NULL, ret = android_get_log_transport());
-  print_transport("android_get_log_transport = ", ret);
-
   pid_t pid = getpid();
 
-  struct logger_list* logger_list;
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
+  struct timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid, ts.tv_sec, ts.tv_nsec);
+  static const char tag[] = "liblog.__android_log_write__android_logger_list_read";
+  static const char prio = ANDROID_LOG_DEBUG;
 
-  log_time ts(CLOCK_MONOTONIC);
-  EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
+  std::string expected_message =
+      std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf + std::string("", 1);
 
-  usleep(1000000);
+  auto write_function = [&] { ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str())); };
 
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if (log_msg.entry.len != expected_message.length()) {
+      return;
     }
 
-    EXPECT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.len != sizeof(android_log_event_long_t)) ||
-        (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+    if (expected_message != std::string(log_msg.msg(), log_msg.entry.len)) {
+      return;
     }
 
-    android_log_event_long_t* eventData;
-    eventData = reinterpret_cast<android_log_event_long_t*>(log_msg.msg());
+    *found = true;
+  };
 
-    if (!eventData || (eventData->payload.type != EVENT_TYPE_LONG)) {
-      continue;
-    }
+  RunLogTests(LOG_ID_MAIN, write_function, check_function);
 
-    log_time tx(reinterpret_cast<char*>(&eventData->payload.data));
-    if (ts == tx) {
-      ++count;
-    }
-  }
-
-  android_logger_list_close(logger_list);
-
-  EXPECT_EQ(logger, ret = android_set_log_transport(logger));
-  print_transport("android_set_log_transport = ", ret);
-  EXPECT_EQ(logger, ret = android_get_log_transport());
-  print_transport("android_get_log_transport = ", ret);
-
-  // False negative if liblog.__android_log_btwrite__android_logger_list_read
-  // fails above, so we will likely succeed. But we will have so many
-  // failures elsewhere that it is probably not worthwhile for us to
-  // highlight yet another disappointment.
-  //
-  // We also expect failures in the following tests if the set does not
-  // react in an appropriate manner internally, yet passes, so we depend
-  // on this test being in the middle of a series of tests performed in
-  // the same process.
-  EXPECT_EQ(0, count);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-#ifdef TEST_PREFIX
-static inline uint32_t get4LE(const uint8_t* src) {
-  return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-static inline uint32_t get4LE(const char* src) {
-  return get4LE(reinterpret_cast<const uint8_t*>(src));
-}
-#endif
-
 static void bswrite_test(const char* message) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-  struct logger_list* logger_list;
-
+#ifdef __ANDROID__
   pid_t pid = getpid();
 
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-#ifdef __ANDROID__
   log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
 
-  EXPECT_LT(0, __android_log_bswrite(0, message));
   size_t num_lines = 1, size = 0, length = 0, total = 0;
   const char* cp = message;
   while (*cp) {
@@ -428,36 +357,25 @@
     ++cp;
     ++total;
   }
-  usleep(1000000);
 
-  int count = 0;
+  auto write_function = [&] { EXPECT_LT(0, __android_log_bswrite(0, message)); };
 
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len !=
-         (sizeof(android_log_event_string_t) + length)) ||
-        (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if ((size_t)log_msg.entry.len != (sizeof(android_log_event_string_t) + length) ||
+        log_msg.id() != LOG_ID_EVENTS) {
+      return;
     }
 
     android_log_event_string_t* eventData;
     eventData = reinterpret_cast<android_log_event_string_t*>(log_msg.msg());
 
     if (!eventData || (eventData->type != EVENT_TYPE_STRING)) {
-      continue;
+      return;
     }
 
-    size_t len = get4LE(reinterpret_cast<char*>(&eventData->length));
+    size_t len = eventData->length;
     if (len == total) {
-      ++count;
+      *found = true;
 
       AndroidLogFormat* logformat = android_log_format_new();
       EXPECT_TRUE(NULL != logformat);
@@ -467,7 +385,7 @@
         fprintf(stderr, "Expect \"Binary log entry conversion failed\"\n");
       }
       int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
-          &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
+          &log_msg.entry, &entry, nullptr, msgBuf, sizeof(msgBuf));
       EXPECT_EQ((length == total) ? 0 : -1, processBinaryLogBuffer);
       if ((processBinaryLogBuffer == 0) || entry.message) {
         size_t line_overhead = 20;
@@ -484,11 +402,10 @@
       }
       android_log_format_free(logformat);
     }
-  }
+  };
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
 
-  android_logger_list_close(logger_list);
 #else
   message = NULL;
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -516,26 +433,15 @@
 }
 
 static void buf_write_test(const char* message) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-  struct logger_list* logger_list;
-
+#ifdef __ANDROID__
   pid_t pid = getpid();
 
-  ASSERT_TRUE(
-      NULL !=
-      (logger_list = android_logger_list_open(
-           LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
   static const char tag[] = "TEST__android_log_buf_write";
-#ifdef __ANDROID__
   log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
 
-  EXPECT_LT(
-      0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
+  auto write_function = [&] {
+    EXPECT_LT(0, __android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO, tag, message));
+  };
   size_t num_lines = 1, size = 0, length = 0;
   const char* cp = message;
   while (*cp) {
@@ -552,32 +458,18 @@
     }
     ++cp;
   }
-  usleep(1000000);
 
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2) || log_msg.id() != LOG_ID_MAIN) {
+      return;
     }
 
-    ASSERT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len != (sizeof(tag) + length + 2)) ||
-        (log_msg.id() != LOG_ID_MAIN)) {
-      continue;
-    }
-
-    ++count;
+    *found = true;
 
     AndroidLogFormat* logformat = android_log_format_new();
     EXPECT_TRUE(NULL != logformat);
     AndroidLogEntry entry;
-    int processLogBuffer =
-        android_log_processLogBuffer(&log_msg.entry_v1, &entry);
+    int processLogBuffer = android_log_processLogBuffer(&log_msg.entry, &entry);
     EXPECT_EQ(0, processLogBuffer);
     if (processLogBuffer == 0) {
       size_t line_overhead = 11;
@@ -588,11 +480,10 @@
                 android_log_printLogLine(logformat, fileno(stderr), &entry));
     }
     android_log_format_free(logformat);
-  }
+  };
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  RunLogTests(LOG_ID_MAIN, write_function, check_function);
 
-  android_logger_list_close(logger_list);
 #else
   message = NULL;
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -611,8 +502,8 @@
   buf_write_test("\n Hello World \n");
 }
 
-#ifdef USING_LOGGER_DEFAULT  // requires blocking reader functionality
-#ifdef TEST_PREFIX
+#ifdef ENABLE_FLAKY_TESTS
+#ifdef __ANDROID__
 static unsigned signaled;
 static log_time signal_time;
 
@@ -673,8 +564,7 @@
 #endif
 
 TEST(liblog, android_logger_list_read__cpu_signal) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
   unsigned long long v = 0xDEADBEEFA55A0000ULL;
 
@@ -766,7 +656,7 @@
 #endif
 }
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 /*
  *  Strictly, we are not allowed to log messages in a signal context, the
  * correct way to handle this is to ensure the messages are constructed in
@@ -830,8 +720,7 @@
 #endif
 
 TEST(liblog, android_logger_list_read__cpu_thread) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   struct logger_list* logger_list;
   unsigned long long v = 0xDEADBEAFA55A0000ULL;
 
@@ -923,13 +812,8 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
+#endif  // ENABLE_FLAKY_TESTS
 
-#ifdef TEST_PREFIX
-static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
-#define SIZEOF_MAX_PAYLOAD_BUF \
-  (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(max_payload_tag) - 1)
-#endif
 static const char max_payload_buf[] =
     "LEONATO\n\
 I learn in this letter that Don Peter of Arragon\n\
@@ -1063,39 +947,26 @@
 takes his leave.";
 
 TEST(liblog, max_payload) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
+  static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
+#define SIZEOF_MAX_PAYLOAD_BUF (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(max_payload_tag) - 1)
+
   pid_t pid = getpid();
   char tag[sizeof(max_payload_tag)];
   memcpy(tag, max_payload_tag, sizeof(tag));
   snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
 
-  LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO,
-                                            tag, max_payload_buf));
-  sleep(2);
+  auto write_function = [&] {
+    LOG_FAILURE_RETRY(
+        __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, max_payload_buf));
+  };
 
-  struct logger_list* logger_list;
-
-  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-                           LOG_ID_SYSTEM, ANDROID_LOG_RDONLY, 100, 0)));
-
-  bool matches = false;
   ssize_t max_len = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
-      continue;
-    }
-
+  auto check_function = [&](log_msg log_msg, bool* found) {
     char* data = log_msg.msg();
 
     if (!data || strcmp(++data, tag)) {
-      continue;
+      return;
     }
 
     data += strlen(data) + 1;
@@ -1112,71 +983,36 @@
     }
 
     if (max_len > 512) {
-      matches = true;
-      break;
+      *found = true;
     }
-  }
+  };
 
-  android_logger_list_close(logger_list);
-
-#if SUPPORTS_END_TO_END
-  EXPECT_EQ(true, matches);
+  RunLogTests(LOG_ID_SYSTEM, write_function, check_function);
 
   EXPECT_LE(SIZEOF_MAX_PAYLOAD_BUF, static_cast<size_t>(max_len));
 #else
-  EXPECT_EQ(false, matches);
-#endif
-#else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
 TEST(liblog, __android_log_buf_print__maxtag) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
-  struct logger_list* logger_list;
-
-  pid_t pid = getpid();
-
-  ASSERT_TRUE(
-      NULL !=
-      (logger_list = android_logger_list_open(
-           LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
 #ifdef __ANDROID__
-  log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
+  auto write_function = [&] {
+    EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO, max_payload_buf,
+                                         max_payload_buf));
+  };
 
-  EXPECT_LT(0, __android_log_buf_print(LOG_ID_MAIN, ANDROID_LOG_INFO,
-                                       max_payload_buf, max_payload_buf));
-  usleep(1000000);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if ((size_t)log_msg.entry.len < LOGGER_ENTRY_MAX_PAYLOAD) {
+      return;
     }
 
-    ASSERT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len < LOGGER_ENTRY_MAX_PAYLOAD) ||
-        (log_msg.id() != LOG_ID_MAIN)) {
-      continue;
-    }
-
-    ++count;
+    *found = true;
 
     AndroidLogFormat* logformat = android_log_format_new();
     EXPECT_TRUE(NULL != logformat);
     AndroidLogEntry entry;
-    int processLogBuffer =
-        android_log_processLogBuffer(&log_msg.entry_v1, &entry);
+    int processLogBuffer = android_log_processLogBuffer(&log_msg.entry, &entry);
     EXPECT_EQ(0, processLogBuffer);
     if (processLogBuffer == 0) {
       fflush(stderr);
@@ -1188,19 +1024,20 @@
       EXPECT_GT(LOGGER_ENTRY_MAX_PAYLOAD * 13 / 8, printLogLine);
     }
     android_log_format_free(logformat);
-  }
+  };
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+  RunLogTests(LOG_ID_MAIN, write_function, check_function);
 
-  android_logger_list_close(logger_list);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
+// TODO: This test is tautological. android_logger_list_read() calls recv() with
+// LOGGER_ENTRY_MAX_PAYLOAD as its size argument, so it's not possible for this test to read a
+// payload larger than that size.
 TEST(liblog, too_big_payload) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
   pid_t pid = getpid();
   static const char big_payload_tag[] = "TEST_big_payload_XXXX";
   char tag[sizeof(big_payload_tag)];
@@ -1208,32 +1045,18 @@
   snprintf(tag + sizeof(tag) - 5, 5, "%04X", pid & 0xFFFF);
 
   std::string longString(3266519, 'x');
+  ssize_t ret;
 
-  ssize_t ret = LOG_FAILURE_RETRY(__android_log_buf_write(
-      LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, longString.c_str()));
+  auto write_function = [&] {
+    ret = LOG_FAILURE_RETRY(
+        __android_log_buf_write(LOG_ID_SYSTEM, ANDROID_LOG_INFO, tag, longString.c_str()));
+  };
 
-  struct logger_list* logger_list;
-
-  ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
-                           LOG_ID_SYSTEM,
-                           ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 100, 0)));
-
-  ssize_t max_len = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    if ((log_msg.entry.pid != pid) || (log_msg.id() != LOG_ID_SYSTEM)) {
-      continue;
-    }
-
+  auto check_function = [&](log_msg log_msg, bool* found) {
     char* data = log_msg.msg();
 
     if (!data || strcmp(++data, tag)) {
-      continue;
+      return;
     }
 
     data += strlen(data) + 1;
@@ -1245,37 +1068,38 @@
       ++right;
     }
 
-    if (max_len <= (left - data)) {
-      max_len = left - data + 1;
+    ssize_t len = left - data + 1;
+    // Check that we don't see any entries larger than the max payload.
+    EXPECT_LE(static_cast<size_t>(len), LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag));
+
+    // Once we've found our expected entry, break.
+    if (len == LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag)) {
+      EXPECT_EQ(ret, len + static_cast<ssize_t>(sizeof(big_payload_tag)));
+      *found = true;
     }
-  }
+  };
 
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_SYSTEM, write_function, check_function);
 
-#if !SUPPORTS_END_TO_END
-  max_len =
-      max_len ? max_len : LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag);
-#endif
-  EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
-            static_cast<size_t>(max_len));
-
-  // SLOP: Allow the underlying interface to optionally place a
-  // terminating nul at the LOGGER_ENTRY_MAX_PAYLOAD's last byte
-  // or not.
-  if (ret == (max_len + static_cast<ssize_t>(sizeof(big_payload_tag)) - 1)) {
-    --max_len;
-  }
-  EXPECT_EQ(ret, max_len + static_cast<ssize_t>(sizeof(big_payload_tag)));
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
 TEST(liblog, dual_reader) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
+  static const int expected_count1 = 25;
+  static const int expected_count2 = 25;
 
-  static const int num = 25;
+  pid_t pid = getpid();
+
+  auto logger_list1 = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count1, pid)};
+  ASSERT_TRUE(logger_list1);
+
+  auto logger_list2 = std::unique_ptr<struct logger_list, ListCloser>{
+      android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count2, pid)};
+  ASSERT_TRUE(logger_list2);
 
   for (int i = 25; i > 0; --i) {
     static const char fmt[] = "dual_reader %02d";
@@ -1284,32 +1108,46 @@
     LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
                                               "liblog", buffer));
   }
-  usleep(1000000);
 
-  struct logger_list* logger_list1;
-  ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
-                           LOG_ID_MAIN,
-                           ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, num, 0)));
+  alarm(2);
+  auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
 
-  struct logger_list* logger_list2;
+  // Wait until we see all messages with the blocking reader.
+  int count1 = 0;
+  int count2 = 0;
 
-  if (NULL == (logger_list2 = android_logger_list_open(
-                   LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   num - 10, 0))) {
-    android_logger_list_close(logger_list1);
-    ASSERT_TRUE(NULL != logger_list2);
+  while (count1 != expected_count2 || count2 != expected_count2) {
+    log_msg log_msg;
+    if (count1 < expected_count1) {
+      ASSERT_GT(android_logger_list_read(logger_list1.get(), &log_msg), 0);
+      count1++;
+    }
+    if (count2 < expected_count2) {
+      ASSERT_GT(android_logger_list_read(logger_list2.get(), &log_msg), 0);
+      count2++;
+    }
   }
 
-  int count1 = 0;
+  // Test again with the nonblocking reader.
+  auto logger_list_non_block1 =
+      std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+          LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count1, pid)};
+  ASSERT_TRUE(logger_list_non_block1);
+
+  auto logger_list_non_block2 =
+      std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+          LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count2, pid)};
+  ASSERT_TRUE(logger_list_non_block2);
+  count1 = 0;
+  count2 = 0;
   bool done1 = false;
-  int count2 = 0;
   bool done2 = false;
 
-  do {
+  while (!done1 || !done2) {
     log_msg log_msg;
 
     if (!done1) {
-      if (android_logger_list_read(logger_list1, &log_msg) <= 0) {
+      if (android_logger_list_read(logger_list_non_block1.get(), &log_msg) <= 0) {
         done1 = true;
       } else {
         ++count1;
@@ -1317,25 +1155,21 @@
     }
 
     if (!done2) {
-      if (android_logger_list_read(logger_list2, &log_msg) <= 0) {
+      if (android_logger_list_read(logger_list_non_block2.get(), &log_msg) <= 0) {
         done2 = true;
       } else {
         ++count2;
       }
     }
-  } while ((!done1) || (!done2));
+  }
 
-  android_logger_list_close(logger_list1);
-  android_logger_list_close(logger_list2);
-
-  EXPECT_EQ(num * SUPPORTS_END_TO_END, count1);
-  EXPECT_EQ((num - 10) * SUPPORTS_END_TO_END, count2);
+  EXPECT_EQ(expected_count1, count1);
+  EXPECT_EQ(expected_count2, count2);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest logprint
 static bool checkPriForTag(AndroidLogFormat* p_format, const char* tag,
                            android_LogPriority pri) {
   return android_log_shouldPrintLine(p_format, tag, pri) &&
@@ -1411,9 +1245,8 @@
 
   android_log_format_free(p_format);
 }
-#endif  // USING_LOGGER_DEFAULT
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest property handling
+#ifdef ENABLE_FLAKY_TESTS
 TEST(liblog, is_loggable) {
 #ifdef __ANDROID__
   static const char tag[] = "is_loggable";
@@ -1701,14 +1534,13 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
+#endif  // ENABLE_FLAKY_TESTS
 
+#ifdef ENABLE_FLAKY_TESTS
 // Following tests the specific issues surrounding error handling wrt logd.
 // Kills logd and toss all collected data, equivalent to logcat -b all -c,
 // except we also return errors to the logging callers.
-#ifdef USING_LOGGER_DEFAULT
 #ifdef __ANDROID__
-#ifdef TEST_PREFIX
 // helper to liblog.enoent to count end-to-end matching logging messages.
 static int count_matching_ts(log_time ts) {
   usleep(1000000);
@@ -1744,21 +1576,18 @@
   return count;
 }
 
-// meant to be handed to ASSERT_TRUE / EXPECT_TRUE only to expand the message
-static testing::AssertionResult IsOk(bool ok, std::string& message) {
-  return ok ? testing::AssertionSuccess()
-            : (testing::AssertionFailure() << message);
-}
-#endif  // TEST_PREFIX
-
 TEST(liblog, enoent) {
-#ifdef TEST_PREFIX
-  TEST_PREFIX
+#ifdef __ANDROID__
+  if (getuid() != 0) {
+    GTEST_SKIP() << "Skipping test, must be run as root.";
+    return;
+  }
+
   log_time ts(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-  EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
+  EXPECT_EQ(1, count_matching_ts(ts));
 
-  // This call will fail if we are setuid(AID_SYSTEM), beware of any
+  // This call will fail unless we are root, beware of any
   // test prior to this one playing with setuid and causing interference.
   // We need to run before these tests so that they do not interfere with
   // this test.
@@ -1770,20 +1599,7 @@
   // liblog.android_logger_get_ is one of those tests that has no recourse
   // and that would be adversely affected by emptying the log if it was run
   // right after this test.
-  if (getuid() != AID_ROOT) {
-    fprintf(
-        stderr,
-        "WARNING: test conditions request being run as root and not AID=%d\n",
-        getuid());
-    if (!__android_log_is_debuggable()) {
-      fprintf(
-          stderr,
-          "WARNING: can not run test on a \"user\" build, bypassing test\n");
-      return;
-    }
-  }
-
-  system((getuid() == AID_ROOT) ? "stop logd" : "su 0 stop logd");
+  system("stop logd");
   usleep(1000000);
 
   // A clean stop like we are testing returns -ENOENT, but in the _real_
@@ -1795,38 +1611,34 @@
   std::string content = android::base::StringPrintf(
       "__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) = %d %s\n",
       ret, (ret <= 0) ? strerror(-ret) : "(content sent)");
-  EXPECT_TRUE(
-      IsOk((ret == -ENOENT) || (ret == -ENOTCONN) || (ret == -ECONNREFUSED),
-           content));
+  EXPECT_TRUE(ret == -ENOENT || ret == -ENOTCONN || ret == -ECONNREFUSED) << content;
   ret = __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts));
   content = android::base::StringPrintf(
       "__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) = %d %s\n",
       ret, (ret <= 0) ? strerror(-ret) : "(content sent)");
-  EXPECT_TRUE(
-      IsOk((ret == -ENOENT) || (ret == -ENOTCONN) || (ret == -ECONNREFUSED),
-           content));
+  EXPECT_TRUE(ret == -ENOENT || ret == -ENOTCONN || ret == -ECONNREFUSED) << content;
   EXPECT_EQ(0, count_matching_ts(ts));
 
-  system((getuid() == AID_ROOT) ? "start logd" : "su 0 start logd");
+  system("start logd");
   usleep(1000000);
 
   EXPECT_EQ(0, count_matching_ts(ts));
 
   ts = log_time(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
-  EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
+  EXPECT_EQ(1, count_matching_ts(ts));
 
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 #endif  // __ANDROID__
-#endif  // USING_LOGGER_DEFAULT
+#endif  // ENABLE_FLAKY_TESTS
 
 // Below this point we run risks of setuid(AID_SYSTEM) which may affect others.
 
+#ifdef ENABLE_FLAKY_TESTS
 // Do not retest properties, and cannot log into LOG_ID_SECURITY
-#ifdef USING_LOGGER_DEFAULT
 TEST(liblog, __security) {
 #ifdef __ANDROID__
   static const char persist_key[] = "persist.logd.security";
@@ -2083,113 +1895,74 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
+#endif  // ENABLE_FLAKY_TESTS
 
-#ifdef TEST_PREFIX
-static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
-                                                 int UID, const char* payload,
-                                                 int DATA_LEN, int& count) {
-  TEST_PREFIX
-  struct logger_list* logger_list;
+#ifdef __ANDROID__
+static void android_errorWriteWithInfoLog_helper(int tag, const char* subtag, int uid,
+                                                 const char* payload, int data_len) {
+  auto write_function = [&] {
+    int ret = android_errorWriteWithInfoLog(tag, subtag, uid, payload, data_len);
+    ASSERT_LT(0, ret);
+  };
 
-  pid_t pid = getpid();
-
-  count = 0;
-
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  int retval_android_errorWriteWithinInfoLog =
-      android_errorWriteWithInfoLog(TAG, SUBTAG, UID, payload, DATA_LEN);
-  if (payload) {
-    ASSERT_LT(0, retval_android_errorWriteWithinInfoLog);
-  } else {
-    ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
-  }
-
-  sleep(2);
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    char* eventData = log_msg.msg();
-    if (!eventData) {
-      continue;
-    }
-
-    char* original = eventData;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    char* event_data = log_msg.msg();
+    char* original = event_data;
 
     // Tag
-    int tag = get4LE(eventData);
-    eventData += 4;
-
-    if (tag != TAG) {
-      continue;
-    }
-
-    if (!payload) {
-      // This tag should not have been written because the data was null
-      ++count;
-      break;
+    auto* event_header = reinterpret_cast<android_event_header_t*>(event_data);
+    event_data += sizeof(android_event_header_t);
+    if (event_header->tag != tag) {
+      return;
     }
 
     // List type
-    ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
-    eventData++;
-
-    // Number of elements in list
-    ASSERT_EQ(3, eventData[0]);
-    eventData++;
+    auto* event_list = reinterpret_cast<android_event_list_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
+    ASSERT_EQ(3, event_list->element_count);
+    event_data += sizeof(android_event_list_t);
 
     // Element #1: string type for subtag
-    ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
-    eventData++;
-
-    unsigned subtag_len = strlen(SUBTAG);
-    if (subtag_len > 32) subtag_len = 32;
-    ASSERT_EQ(subtag_len, get4LE(eventData));
-    eventData += 4;
-
-    if (memcmp(SUBTAG, eventData, subtag_len)) {
-      continue;
+    auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
+    int32_t subtag_len = strlen(subtag);
+    if (subtag_len > 32) {
+      subtag_len = 32;
     }
-    eventData += subtag_len;
+    ASSERT_EQ(subtag_len, event_string_subtag->length);
+    if (memcmp(subtag, &event_string_subtag->data, subtag_len)) {
+      return;
+    }
+    event_data += sizeof(android_event_string_t) + subtag_len;
 
     // Element #2: int type for uid
-    ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
-    eventData++;
-
-    ASSERT_EQ(UID, (int)get4LE(eventData));
-    eventData += 4;
+    auto* event_int_uid = reinterpret_cast<android_event_int_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_INT, event_int_uid->type);
+    ASSERT_EQ(uid, event_int_uid->data);
+    event_data += sizeof(android_event_int_t);
 
     // Element #3: string type for data
-    ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
-    eventData++;
-
-    size_t dataLen = get4LE(eventData);
-    eventData += 4;
-    if (DATA_LEN < 512) ASSERT_EQ(DATA_LEN, (int)dataLen);
-
-    if (memcmp(payload, eventData, dataLen)) {
-      continue;
+    auto* event_string_data = reinterpret_cast<android_event_string_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string_data->type);
+    int32_t message_data_len = event_string_data->length;
+    if (data_len < 512) {
+      ASSERT_EQ(data_len, message_data_len);
     }
+    if (memcmp(payload, &event_string_data->data, message_data_len) != 0) {
+      return;
+    }
+    event_data += sizeof(android_event_string_t);
 
-    if (DATA_LEN >= 512) {
-      eventData += dataLen;
+    if (data_len >= 512) {
+      event_data += message_data_len;
       // 4 bytes for the tag, and max_payload_buf should be truncated.
-      ASSERT_LE(4 + 512, eventData - original);       // worst expectations
-      ASSERT_GT(4 + DATA_LEN, eventData - original);  // must be truncated
+      ASSERT_LE(4 + 512, event_data - original);       // worst expectations
+      ASSERT_GT(4 + data_len, event_data - original);  // must be truncated
     }
+    *found = true;
+  };
 
-    ++count;
-  }
-
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
 }
 #endif
 
@@ -2203,11 +1976,8 @@
 #endif
 
 TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
-#ifdef TEST_PREFIX
-  int count;
-  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1,
-                                       max_payload_buf, 200, count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+#ifdef __ANDROID__
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(1), "test-subtag", -1, max_payload_buf, 200);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2215,24 +1985,21 @@
 
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
-#ifdef TEST_PREFIX
-  int count;
-  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1,
-                                       max_payload_buf, sizeof(max_payload_buf),
-                                       count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+#ifdef __ANDROID__
+  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(2), "test-subtag", -1, max_payload_buf,
+                                       sizeof(max_payload_buf));
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
+// TODO: Do we need to check that we didn't actually write anything if we return a failure here?
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
-#ifdef TEST_PREFIX
-  int count;
-  android_errorWriteWithInfoLog_helper(UNIQUE_TAG(3), "test-subtag", -1, NULL,
-                                       200, count);
-  EXPECT_EQ(0, count);
+#ifdef __ANDROID__
+  int retval_android_errorWriteWithinInfoLog =
+      android_errorWriteWithInfoLog(UNIQUE_TAG(3), "test-subtag", -1, nullptr, 200);
+  ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2240,12 +2007,9 @@
 
 TEST(liblog,
      android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
-#ifdef TEST_PREFIX
-  int count;
+#ifdef __ANDROID__
   android_errorWriteWithInfoLog_helper(
-      UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1,
-      max_payload_buf, 200, count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+      UNIQUE_TAG(4), "abcdefghijklmnopqrstuvwxyz now i know my abc", -1, max_payload_buf, 200);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
@@ -2259,144 +2023,59 @@
   buf_write_test(max_payload_buf);
 }
 
-#ifdef TEST_PREFIX
-static void android_errorWriteLog_helper(int TAG, const char* SUBTAG,
-                                         int& count) {
-  TEST_PREFIX
-  struct logger_list* logger_list;
-
-  pid_t pid = getpid();
-
-  count = 0;
-
-  // Do a Before and After on the count to measure the effect. Decrement
-  // what we find in Before to set the stage.
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
-    char* eventData = log_msg.msg();
-    if (!eventData) continue;
-
-    // Tag
-    int tag = get4LE(eventData);
-    eventData += 4;
-
-    if (tag != TAG) continue;
-
-    if (!SUBTAG) {
-      // This tag should not have been written because the data was null
-      --count;
-      break;
-    }
-
-    // List type
-    eventData++;
-    // Number of elements in list
-    eventData++;
-    // Element #1: string type for subtag
-    eventData++;
-
-    eventData += 4;
-
-    if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) continue;
-    --count;
-  }
-
-  android_logger_list_close(logger_list);
-
-  // Do an After on the count to measure the effect.
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-  int retval_android_errorWriteLog = android_errorWriteLog(TAG, SUBTAG);
-  if (SUBTAG) {
-    ASSERT_LT(0, retval_android_errorWriteLog);
-  } else {
-    ASSERT_GT(0, retval_android_errorWriteLog);
-  }
-
-  sleep(2);
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    char* eventData = log_msg.msg();
-    if (!eventData) {
-      continue;
-    }
-
-    // Tag
-    int tag = get4LE(eventData);
-    eventData += 4;
-
-    if (tag != TAG) {
-      continue;
-    }
-
-    if (!SUBTAG) {
-      // This tag should not have been written because the data was null
-      ++count;
-      break;
-    }
-
-    // List type
-    ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
-    eventData++;
-
-    // Number of elements in list
-    ASSERT_EQ(3, eventData[0]);
-    eventData++;
-
-    // Element #1: string type for subtag
-    ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
-    eventData++;
-
-    ASSERT_EQ(strlen(SUBTAG), get4LE(eventData));
-    eventData += 4;
-
-    if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
-      continue;
-    }
-    ++count;
-  }
-
-  android_logger_list_close(logger_list);
-}
-#endif
-
 TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
-#ifdef TEST_PREFIX
-  int count;
-  android_errorWriteLog_helper(UNIQUE_TAG(5), "test-subtag", count);
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
+#ifdef __ANDROID__
+  int kTag = UNIQUE_TAG(5);
+  const char* kSubTag = "test-subtag";
+
+  auto write_function = [&] {
+    int retval_android_errorWriteLog = android_errorWriteLog(kTag, kSubTag);
+    ASSERT_LT(0, retval_android_errorWriteLog);
+  };
+
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    char* event_data = log_msg.msg();
+
+    // Tag
+    auto* event_header = reinterpret_cast<android_event_header_t*>(event_data);
+    event_data += sizeof(android_event_header_t);
+    if (event_header->tag != kTag) {
+      return;
+    }
+
+    // List type
+    auto* event_list = reinterpret_cast<android_event_list_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_LIST, event_list->type);
+    ASSERT_EQ(3, event_list->element_count);
+    event_data += sizeof(android_event_list_t);
+
+    // Element #1: string type for subtag
+    auto* event_string_subtag = reinterpret_cast<android_event_string_t*>(event_data);
+    ASSERT_EQ(EVENT_TYPE_STRING, event_string_subtag->type);
+    int32_t subtag_len = strlen(kSubTag);
+    ASSERT_EQ(subtag_len, event_string_subtag->length);
+    if (memcmp(kSubTag, &event_string_subtag->data, subtag_len) == 0) {
+      *found = true;
+    }
+  };
+
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
+
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
 TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
-#ifdef TEST_PREFIX
-  int count;
-  android_errorWriteLog_helper(UNIQUE_TAG(6), NULL, count);
-  EXPECT_EQ(0, count);
+#ifdef __ANDROID__
+  EXPECT_LT(android_errorWriteLog(UNIQUE_TAG(6), nullptr), 0);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
 // Do not retest logger list handling
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static int is_real_element(int type) {
   return ((type == EVENT_TYPE_INT) || (type == EVENT_TYPE_LONG) ||
           (type == EVENT_TYPE_STRING) || (type == EVENT_TYPE_FLOAT));
@@ -2551,9 +2230,9 @@
 
   return 0;
 }
-#endif  // TEST_PREFIX
+#endif  // __ANDROID__
 
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
 static const char* event_test_int32(uint32_t tag, size_t& expected_len) {
   android_log_context ctx;
 
@@ -2807,59 +2486,27 @@
 
 static void create_android_logger(const char* (*fn)(uint32_t tag,
                                                     size_t& expected_len)) {
-  TEST_PREFIX
-  struct logger_list* logger_list;
+  size_t expected_len;
+  const char* expected_string;
+  auto write_function = [&] {
+    expected_string = (*fn)(1005, expected_len);
+    ASSERT_NE(nullptr, expected_string);
+  };
 
   pid_t pid = getpid();
-
-  ASSERT_TRUE(NULL !=
-              (logger_list = android_logger_list_open(
-                   LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
-                   1000, pid)));
-
-#ifdef __ANDROID__
-  log_time ts(android_log_clockid());
-#else
-  log_time ts(CLOCK_REALTIME);
-#endif
-
-  size_t expected_len;
-  const char* expected_string = (*fn)(1005, expected_len);
-
-  if (!expected_string) {
-    android_logger_list_close(logger_list);
-    return;
-  }
-
-  usleep(1000000);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) {
-      break;
-    }
-
-    ASSERT_EQ(log_msg.entry.pid, pid);
-
-    if ((log_msg.entry.sec < (ts.tv_sec - 1)) ||
-        ((ts.tv_sec + 1) < log_msg.entry.sec) ||
-        ((size_t)log_msg.entry.len != expected_len) ||
-        (log_msg.id() != LOG_ID_EVENTS)) {
-      continue;
+  auto check_function = [&](log_msg log_msg, bool* found) {
+    if (static_cast<size_t>(log_msg.entry.len) != expected_len) {
+      return;
     }
 
     char* eventData = log_msg.msg();
 
-    ++count;
-
     AndroidLogFormat* logformat = android_log_format_new();
     EXPECT_TRUE(NULL != logformat);
     AndroidLogEntry entry;
     char msgBuf[1024];
-    int processBinaryLogBuffer = android_log_processBinaryLogBuffer(
-        &log_msg.entry_v1, &entry, NULL, msgBuf, sizeof(msgBuf));
+    int processBinaryLogBuffer =
+        android_log_processBinaryLogBuffer(&log_msg.entry, &entry, nullptr, msgBuf, sizeof(msgBuf));
     EXPECT_EQ(0, processBinaryLogBuffer);
     if (processBinaryLogBuffer == 0) {
       int line_overhead = 20;
@@ -2876,29 +2523,28 @@
     // test buffer reading API
     int buffer_to_string = -1;
     if (eventData) {
-      snprintf(msgBuf, sizeof(msgBuf), "I/[%" PRIu32 "]", get4LE(eventData));
+      auto* event_header = reinterpret_cast<android_event_header_t*>(eventData);
+      eventData += sizeof(android_event_header_t);
+      snprintf(msgBuf, sizeof(msgBuf), "I/[%" PRId32 "]", event_header->tag);
       print_barrier();
       fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
       memset(msgBuf, 0, sizeof(msgBuf));
-      buffer_to_string = android_log_buffer_to_string(
-          eventData + sizeof(uint32_t), log_msg.entry.len - sizeof(uint32_t),
-          msgBuf, sizeof(msgBuf));
+      buffer_to_string =
+          android_log_buffer_to_string(eventData, log_msg.entry.len, msgBuf, sizeof(msgBuf));
       fprintf(stderr, "%s\n", msgBuf);
       print_barrier();
     }
     EXPECT_EQ(0, buffer_to_string);
-    EXPECT_EQ(strlen(expected_string), strlen(msgBuf));
-    EXPECT_EQ(0, strcmp(expected_string, msgBuf));
-  }
+    EXPECT_STREQ(expected_string, msgBuf);
+    *found = true;
+  };
 
-  EXPECT_EQ(SUPPORTS_END_TO_END, count);
-
-  android_logger_list_close(logger_list);
+  RunLogTests(LOG_ID_EVENTS, write_function, check_function);
 }
 #endif
 
 TEST(liblog, create_android_logger_int32) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_int32);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2906,7 +2552,7 @@
 }
 
 TEST(liblog, create_android_logger_int64) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_int64);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2914,7 +2560,7 @@
 }
 
 TEST(liblog, create_android_logger_list_int64) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_list_int64);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2922,7 +2568,7 @@
 }
 
 TEST(liblog, create_android_logger_simple_automagic_list) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_simple_automagic_list);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2930,7 +2576,7 @@
 }
 
 TEST(liblog, create_android_logger_list_empty) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_list_empty);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2938,7 +2584,7 @@
 }
 
 TEST(liblog, create_android_logger_complex_nested_list) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_complex_nested_list);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2946,7 +2592,7 @@
 }
 
 TEST(liblog, create_android_logger_7_level_prefix) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_7_level_prefix);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2954,7 +2600,7 @@
 }
 
 TEST(liblog, create_android_logger_7_level_suffix) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_7_level_suffix);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2962,7 +2608,7 @@
 }
 
 TEST(liblog, create_android_logger_android_log_error_write) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_android_log_error_write);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
@@ -2970,14 +2616,13 @@
 }
 
 TEST(liblog, create_android_logger_android_log_error_write_null) {
-#ifdef TEST_PREFIX
+#ifdef __ANDROID__
   create_android_logger(event_test_android_log_error_write_null);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest logger list handling
 TEST(liblog, create_android_logger_overflow) {
   android_log_context ctx;
 
@@ -3005,23 +2650,7 @@
   ASSERT_TRUE(NULL == ctx);
 }
 
-TEST(liblog, android_log_write_list_buffer) {
-  __android_log_event_list ctx(1005);
-  ctx << 1005 << "tag_def"
-      << "(tag|1),(name|3),(format|3)";
-  std::string buffer(ctx);
-  ctx.close();
-
-  char msgBuf[1024];
-  memset(msgBuf, 0, sizeof(msgBuf));
-  EXPECT_EQ(android_log_buffer_to_string(buffer.data(), buffer.length(), msgBuf,
-                                         sizeof(msgBuf)),
-            0);
-  EXPECT_STREQ(msgBuf, "[1005,tag_def,(tag|1),(name|3),(format|3)]");
-}
-#endif  // USING_LOGGER_DEFAULT
-
-#ifdef USING_LOGGER_DEFAULT  // Do not retest pmsg functionality
+#ifdef ENABLE_FLAKY_TESTS
 #ifdef __ANDROID__
 #ifndef NO_PSTORE
 static const char __pmsg_file[] =
@@ -3099,7 +2728,7 @@
   EXPECT_EQ(ANDROID_LOG_VERBOSE, prio);
   EXPECT_FALSE(NULL == strstr(__pmsg_file, filename));
   EXPECT_EQ(len, sizeof(max_payload_buf));
-  EXPECT_EQ(0, strcmp(max_payload_buf, buf));
+  EXPECT_STREQ(max_payload_buf, buf);
 
   ++signaled;
   if ((len != sizeof(max_payload_buf)) || strcmp(max_payload_buf, buf)) {
@@ -3158,9 +2787,8 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
+#endif  // ENABLE_FLAKY_TESTS
 
-#ifdef USING_LOGGER_DEFAULT  // Do not retest event mapping functionality
 TEST(liblog, android_lookupEventTagNum) {
 #ifdef __ANDROID__
   EventTagMap* map = android_openEventTagMap(NULL);
@@ -3177,4 +2805,3 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
 }
-#endif  // USING_LOGGER_DEFAULT
diff --git a/liblog/tests/liblog_test_default.cpp b/liblog/tests/liblog_test_default.cpp
deleted file mode 100644
index 9fc443c..0000000
--- a/liblog/tests/liblog_test_default.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifdef __ANDROID__
-#include <log/log_transport.h>
-#define TEST_LOGGER LOGGER_DEFAULT
-#endif
-#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr.cpp b/liblog/tests/liblog_test_stderr.cpp
deleted file mode 100644
index abc1b9c..0000000
--- a/liblog/tests/liblog_test_stderr.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <log/log_transport.h>
-#define liblog liblog_stderr
-#define TEST_LOGGER LOGGER_STDERR
-#define USING_LOGGER_STDERR
-#include "liblog_test.cpp"
diff --git a/liblog/tests/log_read_test.cpp b/liblog/tests/log_read_test.cpp
index 443c3ea..1be99aa 100644
--- a/liblog/tests/log_read_test.cpp
+++ b/liblog/tests/log_read_test.cpp
@@ -29,54 +29,6 @@
 // Do not use anything in log/log_time.h despite side effects of the above.
 #include <private/android_logger.h>
 
-TEST(liblog, __android_log_write__android_logger_list_read) {
-#ifdef __ANDROID__
-  pid_t pid = getpid();
-
-  struct logger_list* logger_list;
-  ASSERT_TRUE(
-      NULL !=
-      (logger_list = android_logger_list_open(
-           LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
-  struct timespec ts;
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  std::string buf = android::base::StringPrintf("pid=%u ts=%ld.%09ld", pid,
-                                                ts.tv_sec, ts.tv_nsec);
-  static const char tag[] =
-      "liblog.__android_log_write__android_logger_list_read";
-  static const char prio = ANDROID_LOG_DEBUG;
-  ASSERT_LT(0, __android_log_write(prio, tag, buf.c_str()));
-  usleep(1000000);
-
-  buf = std::string(&prio, sizeof(prio)) + tag + std::string("", 1) + buf +
-        std::string("", 1);
-
-  int count = 0;
-
-  for (;;) {
-    log_msg log_msg;
-    if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
-    EXPECT_EQ(log_msg.entry.pid, pid);
-    // There may be a future where we leak "liblog" tagged LOG_ID_EVENT
-    // binary messages through so that logger losses can be correlated?
-    EXPECT_EQ(log_msg.id(), LOG_ID_MAIN);
-
-    if (log_msg.entry.len != buf.length()) continue;
-
-    if (buf != std::string(log_msg.msg(), log_msg.entry.len)) continue;
-
-    ++count;
-  }
-  android_logger_list_close(logger_list);
-
-  EXPECT_EQ(1, count);
-#else
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
 TEST(liblog, android_logger_get_) {
 #ifdef __ANDROID__
   // This test assumes the log buffers are filled with noise from
diff --git a/liblog/tests/log_wrap_test.cpp b/liblog/tests/log_wrap_test.cpp
index ebf0b15..e06964f 100644
--- a/liblog/tests/log_wrap_test.cpp
+++ b/liblog/tests/log_wrap_test.cpp
@@ -27,12 +27,9 @@
 #include <log/log_properties.h>
 #include <log/log_read.h>
 #include <log/log_time.h>
-#include <log/log_transport.h>
 
 #ifdef __ANDROID__
 static void read_with_wrap() {
-  android_set_log_transport(LOGGER_LOGD);
-
   // Read the last line in the log to get a starting timestamp. We're assuming
   // the log is not empty.
   const int mode = ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
@@ -61,60 +58,27 @@
 
   android_logger_list_close(logger_list);
 }
-
-static void caught_signal(int /* signum */) {
-}
 #endif
 
 // b/64143705 confirm fixed
 TEST(liblog, wrap_mode_blocks) {
 #ifdef __ANDROID__
+  // The read call is expected to take up to 2 hours in the happy case.  There was a previous bug
+  // where it would take only 30 seconds due to an alarm() in logd_reader.cpp.  That alarm has been
+  // removed, so we check here that the read call blocks for a reasonable amount of time (5s).
+
+  struct sigaction ignore = {.sa_handler = [](int) { _exit(0); }};
+  struct sigaction old_sigaction;
+  sigaction(SIGALRM, &ignore, &old_sigaction);
+  alarm(5);
 
   android::base::Timer timer;
+  read_with_wrap();
 
-  // The read call is expected to take up to 2 hours in the happy case.
-  // We only want to make sure it waits for longer than 30s, but we can't
-  // use an alarm as the implementation uses it. So we run the test in
-  // a separate process.
-  pid_t pid = fork();
-
-  if (pid == 0) {
-    // child
-    read_with_wrap();
-    _exit(0);
-  }
-
-  struct sigaction ignore, old_sigaction;
-  memset(&ignore, 0, sizeof(ignore));
-  ignore.sa_handler = caught_signal;
-  sigemptyset(&ignore.sa_mask);
-  sigaction(SIGALRM, &ignore, &old_sigaction);
-  alarm(45);
-
-  bool killed = false;
-  for (;;) {
-    siginfo_t info = {};
-    // This wait will succeed if the child exits, or fail with EINTR if the
-    // alarm goes off first - a loose approximation to a timed wait.
-    int ret = waitid(P_PID, pid, &info, WEXITED);
-    if (ret >= 0 || errno != EINTR) {
-      EXPECT_EQ(ret, 0);
-      if (!killed) {
-        EXPECT_EQ(info.si_status, 0);
-      }
-      break;
-    }
-    unsigned int alarm_left = alarm(0);
-    if (alarm_left > 0) {
-      alarm(alarm_left);
-    } else {
-      kill(pid, SIGTERM);
-      killed = true;
-    }
-  }
+  FAIL() << "read_with_wrap() should not return before the alarm is triggered.";
 
   alarm(0);
-  EXPECT_GT(timer.duration(), std::chrono::seconds(40));
+  sigaction(SIGALRM, &old_sigaction, nullptr);
 #else
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/liblog/tests/logprint_test.cpp b/liblog/tests/logprint_test.cpp
new file mode 100644
index 0000000..7ca02ac
--- /dev/null
+++ b/liblog/tests/logprint_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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>
+
+size_t convertPrintable(char* p, const char* message, size_t messageLen);
+
+TEST(liblog, convertPrintable_ascii) {
+  auto input = "easy string, output same";
+  auto output_size = convertPrintable(nullptr, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(input));
+
+  char output[output_size];
+
+  output_size = convertPrintable(output, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(input));
+  EXPECT_STREQ(input, output);
+}
+
+TEST(liblog, convertPrintable_escapes) {
+  // Note that \t is not escaped.
+  auto input = "escape\a\b\t\v\f\r\\";
+  auto expected_output = "escape\\a\\b\t\\v\\f\\r\\\\";
+  auto output_size = convertPrintable(nullptr, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(expected_output));
+
+  char output[output_size];
+
+  output_size = convertPrintable(output, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(expected_output));
+  EXPECT_STREQ(expected_output, output);
+}
+
+TEST(liblog, convertPrintable_validutf8) {
+  auto input = u8"¢ह€𐍈";
+  auto output_size = convertPrintable(nullptr, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(input));
+
+  char output[output_size];
+
+  output_size = convertPrintable(output, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(input));
+  EXPECT_STREQ(input, output);
+}
+
+TEST(liblog, convertPrintable_invalidutf8) {
+  auto input = "\x80\xC2\x01\xE0\xA4\x06\xE0\x06\xF0\x90\x8D\x06\xF0\x90\x06\xF0\x0E";
+  auto expected_output =
+      "\\x80\\xC2\\x01\\xE0\\xA4\\x06\\xE0\\x06\\xF0\\x90\\x8D\\x06\\xF0\\x90\\x06\\xF0\\x0E";
+  auto output_size = convertPrintable(nullptr, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(expected_output));
+
+  char output[output_size];
+
+  output_size = convertPrintable(output, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(expected_output));
+  EXPECT_STREQ(expected_output, output);
+}
+
+TEST(liblog, convertPrintable_mixed) {
+  auto input =
+      u8"\x80\xC2¢ह€𐍈\x01\xE0\xA4\x06¢ह€𐍈\xE0\x06\a\b\xF0\x90¢ह€𐍈\x8D\x06\xF0\t\t\x90\x06\xF0\x0E";
+  auto expected_output =
+      u8"\\x80\\xC2¢ह€𐍈\\x01\\xE0\\xA4\\x06¢ह€𐍈\\xE0\\x06\\a\\b\\xF0\\x90¢ह€𐍈\\x8D\\x06\\xF0\t\t"
+      u8"\\x90\\x06\\xF0\\x0E";
+  auto output_size = convertPrintable(nullptr, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(expected_output));
+
+  char output[output_size];
+
+  output_size = convertPrintable(output, input, strlen(input));
+  EXPECT_EQ(output_size, strlen(expected_output));
+  EXPECT_STREQ(expected_output, output);
+}
diff --git a/liblog/tests/rwlock_test.cpp b/liblog/tests/rwlock_test.cpp
new file mode 100644
index 0000000..617d5c4
--- /dev/null
+++ b/liblog/tests/rwlock_test.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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 "../rwlock.h"
+
+#include <chrono>
+#include <shared_mutex>
+#include <thread>
+
+#include <gtest/gtest.h>
+
+using namespace std::literals;
+
+TEST(rwlock, reader_then_reader_lock) {
+  RwLock lock;
+
+  bool thread_ran = false;
+  auto read_guard = std::shared_lock{lock};
+
+  auto reader_thread = std::thread([&] {
+    auto read_guard = std::shared_lock{lock};
+    thread_ran = true;
+  });
+
+  auto end_time = std::chrono::steady_clock::now() + 1s;
+
+  while (std::chrono::steady_clock::now() < end_time) {
+    if (thread_ran) {
+      break;
+    }
+  }
+
+  EXPECT_EQ(true, thread_ran);
+
+  // Unlock the lock in case something went wrong, to ensure that we can still join() the thread.
+  read_guard.unlock();
+  reader_thread.join();
+}
+
+template <template <typename> typename L1, template <typename> typename L2>
+void TestBlockingLocks() {
+  RwLock lock;
+
+  bool thread_ran = false;
+  auto read_guard = L1{lock};
+
+  auto reader_thread = std::thread([&] {
+    auto read_guard = L2{lock};
+    thread_ran = true;
+  });
+
+  auto end_time = std::chrono::steady_clock::now() + 1s;
+
+  while (std::chrono::steady_clock::now() < end_time) {
+    if (thread_ran) {
+      break;
+    }
+  }
+
+  EXPECT_EQ(false, thread_ran);
+
+  read_guard.unlock();
+  reader_thread.join();
+
+  EXPECT_EQ(true, thread_ran);
+}
+
+TEST(rwlock, reader_then_writer_lock) {
+  TestBlockingLocks<std::shared_lock, std::unique_lock>();
+}
+
+TEST(rwlock, writer_then_reader_lock) {
+  TestBlockingLocks<std::unique_lock, std::shared_lock>();
+}
+
+TEST(rwlock, writer_then_writer_lock) {
+  TestBlockingLocks<std::unique_lock, std::unique_lock>();
+}
diff --git a/libmeminfo/.clang-format b/libmeminfo/.clang-format
deleted file mode 120000
index 1af4f51..0000000
--- a/libmeminfo/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-4
\ No newline at end of file
diff --git a/libmeminfo/Android.bp b/libmeminfo/Android.bp
deleted file mode 100644
index fc022bd..0000000
--- a/libmeminfo/Android.bp
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// 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.
-//
-
-cc_defaults {
-    name: "libmeminfo_defaults",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libprocinfo",
-    ],
-}
-
-cc_library {
-    name: "libmeminfo",
-    defaults: ["libmeminfo_defaults"],
-    export_include_dirs: ["include"],
-    export_shared_lib_headers: ["libbase"],
-    srcs: [
-        "pageacct.cpp",
-        "procmeminfo.cpp",
-        "sysmeminfo.cpp",
-    ],
-}
-
-cc_test {
-    name: "libmeminfo_test",
-    defaults: ["libmeminfo_defaults"],
-
-    static_libs: [
-        "libmeminfo",
-        "libbase",
-        "liblog",
-    ],
-
-    srcs: [
-        "libmeminfo_test.cpp"
-    ],
-
-    data: [
-        "testdata1/*",
-        "testdata2/*"
-    ],
-}
-
-cc_benchmark {
-    name: "libmeminfo_benchmark",
-    srcs: [
-        "libmeminfo_benchmark.cpp",
-    ],
-    static_libs : [
-        "libbase",
-        "liblog",
-        "libmeminfo",
-        "libprocinfo",
-    ],
-
-    data: [
-        "testdata1/*",
-    ],
-}
diff --git a/libmeminfo/OWNERS b/libmeminfo/OWNERS
deleted file mode 100644
index 26e71fe..0000000
--- a/libmeminfo/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-sspatil@google.com
diff --git a/libmeminfo/include/meminfo/meminfo.h b/libmeminfo/include/meminfo/meminfo.h
deleted file mode 100644
index 2fc7867..0000000
--- a/libmeminfo/include/meminfo/meminfo.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-namespace android {
-namespace meminfo {
-
-struct MemUsage {
-    uint64_t vss;
-    uint64_t rss;
-    uint64_t pss;
-    uint64_t uss;
-
-    uint64_t swap;
-    uint64_t swap_pss;
-
-    uint64_t private_clean;
-    uint64_t private_dirty;
-    uint64_t shared_clean;
-    uint64_t shared_dirty;
-
-    MemUsage()
-        : vss(0),
-          rss(0),
-          pss(0),
-          uss(0),
-          swap(0),
-          swap_pss(0),
-          private_clean(0),
-          private_dirty(0),
-          shared_clean(0),
-          shared_dirty(0) {}
-
-    ~MemUsage() = default;
-
-    void clear() {
-        vss = rss = pss = uss = swap = swap_pss = 0;
-        private_clean = private_dirty = shared_clean = shared_dirty = 0;
-    }
-};
-
-struct Vma {
-    uint64_t start;
-    uint64_t end;
-    uint64_t offset;
-    uint16_t flags;
-    std::string name;
-
-    Vma() : start(0), end(0), offset(0), flags(0), name("") {}
-    Vma(uint64_t s, uint64_t e, uint64_t off, uint16_t f, const char* n)
-        : start(s), end(e), offset(off), flags(f), name(n) {}
-    ~Vma() = default;
-
-    void clear() { memset(&usage, 0, sizeof(usage)); }
-
-    // Memory usage of this mapping.
-    MemUsage usage;
-};
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/include/meminfo/pageacct.h b/libmeminfo/include/meminfo/pageacct.h
deleted file mode 100644
index 8483d84..0000000
--- a/libmeminfo/include/meminfo/pageacct.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/unique_fd.h>
-
-namespace android {
-namespace meminfo {
-
-class PageAcct final {
-    // Class for per-page accounting by using kernel provided interfaces like
-    // kpagecount, kpageflags etc.
-  public:
-    static bool KernelHasPageIdle() {
-        return (access("/sys/kernel/mm/page_idle/bitmap", R_OK | W_OK) == 0);
-    }
-
-    bool InitPageAcct(bool pageidle_enable = false);
-    bool PageFlags(uint64_t pfn, uint64_t* flags);
-    bool PageMapCount(uint64_t pfn, uint64_t* mapcount);
-
-    int IsPageIdle(uint64_t pfn);
-
-    // The only way to create PageAcct object
-    static PageAcct& Instance() {
-        static PageAcct instance;
-        return instance;
-    }
-
-    ~PageAcct() = default;
-
-  private:
-    PageAcct() : kpagecount_fd_(-1), kpageflags_fd_(-1), pageidle_fd_(-1) {}
-    int MarkPageIdle(uint64_t pfn) const;
-    int GetPageIdle(uint64_t pfn) const;
-
-    // Non-copyable & Non-movable
-    PageAcct(const PageAcct&) = delete;
-    PageAcct& operator=(const PageAcct&) = delete;
-    PageAcct& operator=(PageAcct&&) = delete;
-    PageAcct(PageAcct&&) = delete;
-
-    ::android::base::unique_fd kpagecount_fd_;
-    ::android::base::unique_fd kpageflags_fd_;
-    ::android::base::unique_fd pageidle_fd_;
-};
-
-// Returns if the page present bit is set in the value
-// passed in.
-bool page_present(uint64_t pagemap_val);
-
-// Returns if the page swapped bit is set in the value
-// passed in.
-bool page_swapped(uint64_t pagemap_val);
-
-// Returns the page frame number (physical page) from
-// pagemap value
-uint64_t page_pfn(uint64_t pagemap_val);
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
deleted file mode 100644
index 1fb4151..0000000
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <sys/types.h>
-
-#include <string>
-#include <vector>
-
-#include "meminfo.h"
-
-namespace android {
-namespace meminfo {
-
-using VmaCallback = std::function<void(const Vma&)>;
-
-class ProcMemInfo final {
-    // Per-process memory accounting
-  public:
-    // Reset the working set accounting of the process via /proc/<pid>/clear_refs
-    static bool ResetWorkingSet(pid_t pid);
-
-    ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0);
-
-    const std::vector<Vma>& Maps();
-    const MemUsage& Usage();
-    const MemUsage& Wss();
-
-    // Same as Maps() except, only valid for reading working set using CONFIG_IDLE_PAGE_TRACKING
-    // support in kernel. If the kernel support doesn't exist, the function will return an empty
-    // vector.
-    const std::vector<Vma>& MapsWithPageIdle();
-
-    // Collect all 'vma' or 'maps' from /proc/<pid>/smaps and store them in 'maps_'. Returns a
-    // constant reference to the vma vector after the collection is done.
-    //
-    // Each 'struct Vma' is *fully* populated by this method (unlike SmapsOrRollup).
-    const std::vector<Vma>& Smaps(const std::string& path = "");
-
-    // This method reads /proc/<pid>/smaps and calls the callback() for each
-    // vma or map that it finds. The map is converted to 'struct Vma' object which is then
-    // passed to the callback.
-    // Returns 'false' if the file is malformed.
-    bool ForEachVma(const VmaCallback& callback);
-
-    // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
-    // Pss and Private memory usage in 'stats'.  In particular, the method only populates the fields
-    // of the MemUsage structure that are intended to be used by Android's periodic Pss collection.
-    //
-    // The method populates the following statistics in order to be fast an efficient.
-    //   Pss
-    //   Rss
-    //   Uss
-    //   private_clean
-    //   private_dirty
-    //   SwapPss
-    // All other fields of MemUsage are zeroed.
-    bool SmapsOrRollup(MemUsage* stats) const;
-
-    // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
-    // Pss.
-    // Returns 'true' on success and the value of Pss in the out parameter.
-    bool SmapsOrRollupPss(uint64_t* pss) const;
-
-    const std::vector<uint16_t>& SwapOffsets();
-
-    // Reads /proc/<pid>/pagemap for this process for each page within
-    // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma'
-    // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks
-    // are made to see if 'vma' is *valid*.
-    // Returns false if anything goes wrong, 'true' otherwise.
-    bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap);
-
-    ~ProcMemInfo() = default;
-
-  private:
-    bool ReadMaps(bool get_wss, bool use_pageidle = false);
-    bool ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle);
-
-    pid_t pid_;
-    bool get_wss_;
-    uint64_t pgflags_;
-    uint64_t pgflags_mask_;
-
-    std::vector<Vma> maps_;
-
-    MemUsage usage_;
-    std::vector<uint16_t> swap_offsets_;
-};
-
-// Makes callback for each 'vma' or 'map' found in file provided. The file is expected to be in the
-// same format as /proc/<pid>/smaps. Returns 'false' if the file is malformed.
-bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback);
-
-// Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the
-// calling process has access to the /proc/<pid>/smaps_rollup.
-// Returns 'false' if the calling process has no permission to read the file if it exists
-// of if the file doesn't exist.
-bool IsSmapsRollupSupported(pid_t pid);
-
-// Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly
-// from a file. The file MUST be in the same format as /proc/<pid>/smaps
-// or /proc/<pid>/smaps_rollup
-bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats);
-
-// Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly
-// from a file and returns total Pss in kB. The file MUST be in the same format
-// as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup
-bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss);
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/include/meminfo/sysmeminfo.h b/libmeminfo/include/meminfo/sysmeminfo.h
deleted file mode 100644
index 8388920..0000000
--- a/libmeminfo/include/meminfo/sysmeminfo.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <sys/types.h>
-
-#include <functional>
-#include <map>
-#include <string>
-#include <vector>
-
-namespace android {
-namespace meminfo {
-
-class SysMemInfo final {
-    // System or Global memory accounting
-  public:
-    static constexpr const char* kMemTotal = "MemTotal:";
-    static constexpr const char* kMemFree = "MemFree:";
-    static constexpr const char* kMemBuffers = "Buffers:";
-    static constexpr const char* kMemCached = "Cached:";
-    static constexpr const char* kMemShmem = "Shmem:";
-    static constexpr const char* kMemSlab = "Slab:";
-    static constexpr const char* kMemSReclaim = "SReclaimable:";
-    static constexpr const char* kMemSUnreclaim = "SUnreclaim:";
-    static constexpr const char* kMemSwapTotal = "SwapTotal:";
-    static constexpr const char* kMemSwapFree = "SwapFree:";
-    static constexpr const char* kMemMapped = "Mapped:";
-    static constexpr const char* kMemVmallocUsed = "VmallocUsed:";
-    static constexpr const char* kMemPageTables = "PageTables:";
-    static constexpr const char* kMemKernelStack = "KernelStack:";
-
-    static const std::vector<std::string> kDefaultSysMemInfoTags;
-
-    SysMemInfo() = default;
-
-    // Parse /proc/meminfo and read values that are needed
-    bool ReadMemInfo(const std::string& path = "/proc/meminfo");
-    bool ReadMemInfo(const std::vector<std::string>& tags, std::vector<uint64_t>* out,
-                     const std::string& path = "/proc/meminfo");
-    bool ReadMemInfo(std::vector<uint64_t>* out, const std::string& path = "/proc/meminfo");
-
-    // Parse /proc/vmallocinfo and return total physical memory mapped
-    // in vmalloc area by the kernel.
-    // Note that this deliberately ignores binder buffers. They are _always_
-    // mapped in a process and are counted for in each process.
-    uint64_t ReadVmallocInfo();
-
-    // getters
-    uint64_t mem_total_kb() { return mem_in_kb_[kMemTotal]; }
-    uint64_t mem_free_kb() { return mem_in_kb_[kMemFree]; }
-    uint64_t mem_buffers_kb() { return mem_in_kb_[kMemBuffers]; }
-    uint64_t mem_cached_kb() { return mem_in_kb_[kMemCached]; }
-    uint64_t mem_shmem_kb() { return mem_in_kb_[kMemShmem]; }
-    uint64_t mem_slab_kb() { return mem_in_kb_[kMemSlab]; }
-    uint64_t mem_slab_reclaimable_kb() { return mem_in_kb_[kMemSReclaim]; }
-    uint64_t mem_slab_unreclaimable_kb() { return mem_in_kb_[kMemSUnreclaim]; }
-    uint64_t mem_swap_kb() { return mem_in_kb_[kMemSwapTotal]; }
-    uint64_t mem_swap_free_kb() { return mem_in_kb_[kMemSwapFree]; }
-    uint64_t mem_mapped_kb() { return mem_in_kb_[kMemMapped]; }
-    uint64_t mem_vmalloc_used_kb() { return mem_in_kb_[kMemVmallocUsed]; }
-    uint64_t mem_page_tables_kb() { return mem_in_kb_[kMemPageTables]; }
-    uint64_t mem_kernel_stack_kb() { return mem_in_kb_[kMemKernelStack]; }
-    uint64_t mem_zram_kb(const std::string& zram_dev = "");
-
-  private:
-    std::map<std::string, uint64_t> mem_in_kb_;
-    bool MemZramDevice(const std::string& zram_dev, uint64_t* mem_zram_dev);
-    bool ReadMemInfo(const std::vector<std::string>& tags, const std::string& path,
-                     std::function<void(const std::string&, uint64_t)> store_val);
-};
-
-// Parse /proc/vmallocinfo and return total physical memory mapped
-// in vmalloc area by the kernel. Note that this deliberately ignores binder buffers. They are
-// _always_ mapped in a process and are counted for in each process.
-uint64_t ReadVmallocInfo(const std::string& path = "/proc/vmallocinfo");
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/libdmabufinfo/Android.bp b/libmeminfo/libdmabufinfo/Android.bp
deleted file mode 100644
index 4aed45c..0000000
--- a/libmeminfo/libdmabufinfo/Android.bp
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// 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",
-        "libprocinfo",
-    ],
-    shared_libs: [
-        "liblog",
-    ],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wextra",
-    ],
-}
-
-cc_library_static {
-    name: "libdmabufinfo",
-    vendor_available: true,
-    defaults: ["dmabufinfo_defaults"],
-    export_include_dirs: ["include"],
-    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
deleted file mode 100644
index 9fb22a1..0000000
--- a/libmeminfo/libdmabufinfo/dmabufinfo.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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 <dirent.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>
-
-#include <dmabufinfo/dmabufinfo.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;
-}
-
-// TODO: std::filesystem::is_symlink fails to link on vendor code,
-// forcing this workaround.
-// Move back to libc++fs once it is vendor-available. See b/124012728
-static bool is_symlink(const char *filename)
-{
-    struct stat p_statbuf;
-    if (lstat(filename, &p_statbuf) < 0) {
-        return false;
-    }
-    if (S_ISLNK(p_statbuf.st_mode) == 1) {
-        return true;
-    }
-    return false;
-}
-
-static bool ReadDmaBufFdRefs(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
-    std::string fdpath = ::android::base::StringPrintf("/proc/%d/fd", pid);
-
-    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(fdpath.c_str()), closedir);
-    if (!dir) {
-        LOG(ERROR) << "Failed to open " << fdpath << " directory" << std::endl;
-        return false;
-    }
-    struct dirent* dent;
-    while ((dent = readdir(dir.get()))) {
-        std::string path =
-            ::android::base::StringPrintf("%s/%s", fdpath.c_str(), dent->d_name);
-
-        if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") ||
-            !is_symlink(path.c_str())) {
-            continue;
-        }
-
-        std::string target;
-        if (!::android::base::Readlink(path, &target)) {
-            LOG(ERROR) << "Failed to find target for symlink: " << path;
-            return false;
-        }
-
-        if (!FileIsDmaBuf(target)) {
-            continue;
-        }
-
-        int fd;
-        if (!::android::base::ParseInt(dent->d_name, &fd)) {
-            LOG(ERROR) << "Dmabuf fd: " << path << " 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: " << path;
-            return false;
-        }
-
-        struct stat sb;
-        if (stat(path.c_str(), &sb) < 0) {
-            PLOG(ERROR) << "Failed to stat: " << path;
-            return false;
-        }
-
-        uint64_t inode = sb.st_ino;
-        auto buf = std::find_if(dmabufs->begin(), dmabufs->end(),
-                                [&inode](const DmaBuffer& dbuf) { return dbuf.inode() == inode; });
-        if (buf != dmabufs->end()) {
-            if (buf->name() == "" || buf->name() == "<unknown>") buf->SetName(name);
-            if (buf->exporter() == "" || buf->exporter() == "<unknown>") buf->SetExporter(exporter);
-            if (buf->count() == 0) buf->SetCount(count);
-            buf->AddFdRef(pid);
-            continue;
-        }
-
-        DmaBuffer& db = dmabufs->emplace_back(sb.st_ino, sb.st_blocks * 512, count, exporter, name);
-        db.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 */, ino_t inode, const char* name) {
-        // no need to look into this mapping if it is not dmabuf
-        if (!FileIsDmaBuf(std::string(name))) {
-            return;
-        }
-
-        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();
-    return AppendDmaBufInfo(pid, dmabufs);
-}
-
-bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs) {
-    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
deleted file mode 100644
index eb53e57..0000000
--- a/libmeminfo/libdmabufinfo/dmabufinfo_test.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/* 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 <inttypes.h>
-#include <linux/dma-buf.h>
-#include <poll.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <string>
-#include <unordered_map>
-#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
-
-class fd_sharer {
-  public:
-    fd_sharer();
-    ~fd_sharer() { kill(); }
-
-    bool ok() const { return child_pid > 0; }
-    bool sendfd(int fd);
-    bool kill();
-    pid_t pid() const { return child_pid; }
-
-  private:
-    unique_fd parent_fd, child_fd;
-    pid_t child_pid;
-
-    void run();
-};
-
-fd_sharer::fd_sharer() : parent_fd{}, child_fd{}, child_pid{-1} {
-    bool sp_ok = android::base::Socketpair(SOCK_STREAM, &parent_fd, &child_fd);
-    if (!sp_ok) return;
-
-    child_pid = fork();
-    if (child_pid < 0) return;
-
-    if (child_pid == 0) run();
-}
-
-bool fd_sharer::kill() {
-    int err = ::kill(child_pid, SIGKILL);
-    if (err < 0) return false;
-
-    return ::waitpid(child_pid, nullptr, 0) == child_pid;
-}
-
-void fd_sharer::run() {
-    while (true) {
-        int fd;
-        char unused = 0;
-
-        iovec iov{};
-        iov.iov_base = &unused;
-        iov.iov_len = sizeof(unused);
-
-        msghdr msg{};
-        msg.msg_iov = &iov;
-        msg.msg_iovlen = 1;
-
-        char cmsg_buf[CMSG_SPACE(sizeof(fd))];
-        msg.msg_control = cmsg_buf;
-        msg.msg_controllen = sizeof(cmsg_buf);
-
-        cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
-        cmsg->cmsg_level = SOL_SOCKET;
-        cmsg->cmsg_type = SCM_RIGHTS;
-        cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
-
-        ssize_t s = TEMP_FAILURE_RETRY(recvmsg(child_fd, &msg, 0));
-        if (s == -1) break;
-
-        s = TEMP_FAILURE_RETRY(write(child_fd, &unused, sizeof(unused)));
-        if (s == -1) break;
-    }
-}
-
-bool fd_sharer::sendfd(int fd) {
-    char unused = 0;
-
-    iovec iov{};
-    iov.iov_base = &unused;
-    iov.iov_len = sizeof(unused);
-
-    msghdr msg{};
-    msg.msg_iov = &iov;
-    msg.msg_iovlen = 1;
-
-    char cmsg_buf[CMSG_SPACE(sizeof(fd))];
-    msg.msg_control = cmsg_buf;
-    msg.msg_controllen = sizeof(cmsg_buf);
-
-    cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
-    cmsg->cmsg_level = SOL_SOCKET;
-    cmsg->cmsg_type = SCM_RIGHTS;
-    cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
-
-    int* fd_buf = reinterpret_cast<int*>(CMSG_DATA(cmsg));
-    *fd_buf = fd;
-
-    ssize_t s = TEMP_FAILURE_RETRY(sendmsg(parent_fd, &msg, 0));
-    if (s == -1) return false;
-
-    // The target process installs the fd into its fd table during recvmsg().
-    // So if we return now, there's a brief window between sendfd() finishing
-    // and libmemoryinfo actually seeing that the buffer has been shared.  This
-    // window is just large enough to break tests.
-    //
-    // To work around this, wait for the target process to respond with a dummy
-    // byte, with a timeout of 1 s.
-    pollfd p{};
-    p.fd = parent_fd;
-    p.events = POLL_IN;
-    int ready = poll(&p, 1, 1000);
-    if (ready != 1) return false;
-
-    s = TEMP_FAILURE_RETRY(read(parent_fd, &unused, sizeof(unused)));
-    if (s == -1) return false;
-
-    return true;
-}
-
-#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::unordered_map<pid_t, int>& _fdrefs = _bufptr->fdrefs();   \
-        auto _ref = _fdrefs.find(_pid);                                      \
-        EXPECT_EQ((_ref != _fdrefs.end()), _expect);                         \
-    } while (0)
-
-#define EXPECT_PID_IN_MAPREFS(_bufptr, _pid, _expect)                        \
-    do {                                                                     \
-        const std::unordered_map<pid_t, int>& _maprefs = _bufptr->maprefs(); \
-        auto _ref = _maprefs.find(_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};
-    }
-
-    void readAndCheckDmaBuffer(std::vector<DmaBuffer>* dmabufs, pid_t pid, const std::string name,
-                               size_t fdrefs_size, size_t maprefs_size, const std::string exporter,
-                               size_t refcount, uint64_t buf_size, bool expectFdrefs,
-                               bool expectMapRefs) {
-        EXPECT_TRUE(ReadDmaBufInfo(pid, dmabufs));
-        EXPECT_EQ(dmabufs->size(), 1UL);
-        EXPECT_ONE_BUF_EQ(dmabufs->begin(), name, fdrefs_size, maprefs_size, exporter, refcount,
-                          buf_size);
-        // Make sure the buffer has the right pid too.
-        EXPECT_PID_IN_FDREFS(dmabufs->begin(), pid, expectFdrefs);
-        EXPECT_PID_IN_MAPREFS(dmabufs->begin(), pid, expectMapRefs);
-    }
-
-    bool checkPidRef(DmaBuffer& dmabuf, pid_t pid, int expectFdrefs) {
-        int fdrefs = dmabuf.fdrefs().find(pid)->second;
-        return fdrefs == expectFdrefs;
-    }
-
-  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, true);
-    }
-
-    // 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, true);
-        EXPECT_PID_IN_MAPREFS(dmabufs.begin(), pid, true);
-
-        // 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, false);
-        EXPECT_PID_IN_MAPREFS(dmabufs.begin(), pid, true);
-
-        // 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());
-}
-
-TEST_F(DmaBufTester, TestSharedfd) {
-    // Each time a shared buffer is received over a socket, the remote process
-    // will take an extra reference on it.
-
-    ASSERT_TRUE(is_valid());
-
-    pid_t pid = getpid();
-    std::vector<DmaBuffer> dmabufs;
-    {
-        fd_sharer sharer{};
-        ASSERT_TRUE(sharer.ok());
-        // 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";
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL, true,
-                              false);
-
-        ASSERT_TRUE(sharer.sendfd(buf));
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 2UL, 4096ULL, true,
-                              false);
-        EXPECT_TRUE(checkPidRef(dmabufs[0], pid, 1));
-        readAndCheckDmaBuffer(&dmabufs, sharer.pid(), "dmabuftester-4k", 1UL, 0UL, "ion", 2UL,
-                              4096ULL, true, false);
-        EXPECT_TRUE(checkPidRef(dmabufs[0], sharer.pid(), 1));
-
-        ASSERT_TRUE(sharer.sendfd(buf));
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 3UL, 4096ULL, true,
-                              false);
-        EXPECT_TRUE(checkPidRef(dmabufs[0], pid, 1));
-        readAndCheckDmaBuffer(&dmabufs, sharer.pid(), "dmabuftester-4k", 1UL, 0UL, "ion", 3UL,
-                              4096ULL, true, false);
-        EXPECT_TRUE(checkPidRef(dmabufs[0], sharer.pid(), 2));
-
-        ASSERT_TRUE(sharer.kill());
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL, true,
-                              false);
-    }
-
-    // Now make sure the buffer has disappeared
-    ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
-    EXPECT_TRUE(dmabufs.empty());
-}
-
-TEST_F(DmaBufTester, DupFdTest) {
-    // dup()ing an fd will make this process take an extra reference on the
-    // shared buffer.
-
-    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";
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL, true,
-                              false);
-
-        unique_fd buf2{dup(buf)};
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 2UL, 4096ULL, true,
-                              false);
-        EXPECT_TRUE(checkPidRef(dmabufs[0], pid, 2));
-
-        close(buf2.release());
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL, true,
-                              false);
-        EXPECT_TRUE(checkPidRef(dmabufs[0], pid, 1));
-    }
-
-    // Now make sure the buffer has disappeared
-    ASSERT_TRUE(ReadDmaBufInfo(pid, &dmabufs));
-    EXPECT_TRUE(dmabufs.empty());
-}
-
-TEST_F(DmaBufTester, ForkTest) {
-    // fork()ing a child will cause the child to automatically take a reference
-    // on any existing shared buffers.
-    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";
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL, true,
-                              false);
-        fd_sharer sharer{};
-        ASSERT_TRUE(sharer.ok());
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 2UL, 4096ULL, true,
-                              false);
-        readAndCheckDmaBuffer(&dmabufs, sharer.pid(), "dmabuftester-4k", 1UL, 0UL, "ion", 2UL,
-                              4096ULL, true, false);
-        ASSERT_TRUE(sharer.kill());
-        readAndCheckDmaBuffer(&dmabufs, pid, "dmabuftester-4k", 1UL, 0UL, "ion", 1UL, 4096ULL, true,
-                              false);
-    }
-
-    // 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
deleted file mode 100644
index a6e7f69..0000000
--- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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 <set>
-#include <string>
-#include <vector>
-#include <unordered_map>
-
-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) {
-        total_refs_ = 0;
-    }
-    DmaBuffer() = default;
-    ~DmaBuffer() = default;
-
-    // Adds one file descriptor reference for the given pid
-    void AddFdRef(pid_t pid) {
-        AddRefToPidMap(pid, &fdrefs_);
-        total_refs_++;
-    }
-
-    // Adds one map reference for the given pid
-    void AddMapRef(pid_t pid) {
-        AddRefToPidMap(pid, &maprefs_);
-        total_refs_++;
-    }
-
-    // Getters for each property
-    uint64_t size() const { return size_; }
-    const std::unordered_map<pid_t, int>& fdrefs() const { return fdrefs_; }
-    const std::unordered_map<pid_t, int>& maprefs() const { return maprefs_; }
-    ino_t inode() const { return inode_; }
-    uint64_t total_refs() const { return total_refs_; }
-    uint64_t count() const { return count_; };
-    const std::set<pid_t>& pids() const { return pids_; }
-    const std::string& name() const { return name_; }
-    const std::string& exporter() const { return exporter_; }
-    void SetName(const std::string& name) { name_ = name; }
-    void SetExporter(const std::string& exporter) { exporter_ = exporter; }
-    void SetCount(uint64_t count) { count_ = count; }
-    uint64_t Pss() const { return size_ / pids_.size(); }
-
-    bool operator==(const DmaBuffer& rhs) {
-        return (inode_ == rhs.inode()) && (size_ == rhs.size()) && (name_ == rhs.name()) &&
-               (exporter_ == rhs.exporter());
-    }
-
-  private:
-    ino_t inode_;
-    uint64_t size_;
-    uint64_t count_;
-    uint64_t total_refs_;
-    std::set<pid_t> pids_;
-    std::string exporter_;
-    std::string name_;
-    std::unordered_map<pid_t, int> fdrefs_;
-    std::unordered_map<pid_t, int> maprefs_;
-    void AddRefToPidMap(pid_t pid, std::unordered_map<pid_t, int>* map) {
-        // The first time we find a ref, we set the ref count to 1
-        // otherwise, increment the existing ref count
-        auto [it, inserted] = map->insert(std::make_pair(pid, 1));
-        if (!inserted)
-            it->second++;
-        pids_.insert(pid);
-    }
-};
-
-// 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
-// Returns false if something went wrong with the function, true otherwise.
-bool ReadDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
-
-// Append new dmabuf objects from a given process to an existing vector.
-// When the vector contains an existing element with a matching inode,
-// the reference counts will be updated.
-// Does not depend on DEBUGFS.
-// Returns false if something went wrong with the function, true otherwise.
-bool AppendDmaBufInfo(pid_t pid, std::vector<DmaBuffer>* dmabufs);
-
-}  // namespace dmabufinfo
-}  // namespace android
diff --git a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
deleted file mode 100644
index 48901b1..0000000
--- a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * 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 <dirent.h>
-#include <errno.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <iostream>
-#include <map>
-#include <set>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-#include <dmabufinfo/dmabufinfo.h>
-
-using DmaBuffer = ::android::dmabufinfo::DmaBuffer;
-
-[[noreturn]] static void usage(int exit_status) {
-    fprintf(stderr,
-            "Usage: %s [-ah] [PID] \n"
-            "-a\t show all dma buffers (ion) in big table, [buffer x process] grid \n"
-            "-h\t show this help\n"
-            "  \t If PID is supplied, the dmabuf information for that process is shown.\n",
-            getprogname());
-
-    exit(exit_status);
-}
-
-static std::string GetProcessComm(const pid_t pid) {
-    std::string pid_path = android::base::StringPrintf("/proc/%d/comm", pid);
-    std::ifstream in{pid_path};
-    if (!in) return std::string("N/A");
-    std::string line;
-    std::getline(in, line);
-    if (!in) return std::string("N/A");
-    return line;
-}
-
-static void PrintDmaBufTable(const std::vector<DmaBuffer>& bufs) {
-    if (bufs.empty()) {
-        printf("dmabuf info not found ¯\\_(ツ)_/¯\n");
-        return;
-    }
-
-    // Find all unique pids in the input vector, create a set
-    std::set<pid_t> pid_set;
-    for (auto& buf : bufs) {
-        pid_set.insert(buf.pids().begin(), buf.pids().end());
-    }
-
-    // Format the header string spaced and separated with '|'
-    printf("    Dmabuf Inode |            Size |      Ref Counts |");
-    for (auto pid : pid_set) {
-        printf("%16s:%-5d |", GetProcessComm(pid).c_str(), pid);
-    }
-    printf("\n");
-
-    // holds per-process dmabuf size in kB
-    std::map<pid_t, uint64_t> per_pid_size = {};
-    uint64_t dmabuf_total_size = 0;
-
-    // Iterate through all dmabufs and collect per-process sizes, refs
-    for (auto& buf : bufs) {
-        printf("%16ju |%13" PRIu64 " kB |%16" PRIu64 " |", static_cast<uintmax_t>(buf.inode()),
-               buf.size() / 1024, buf.total_refs());
-        // Iterate through each process to find out per-process references for each buffer,
-        // gather total size used by each process etc.
-        for (pid_t pid : pid_set) {
-            int pid_refs = 0;
-            if (buf.fdrefs().count(pid) == 1) {
-                // Get the total number of ref counts the process is holding
-                // on this buffer. We don't differentiate between mmap or fd.
-                pid_refs += buf.fdrefs().at(pid);
-                if (buf.maprefs().count(pid) == 1) {
-                    pid_refs += buf.maprefs().at(pid);
-                }
-            }
-
-            if (pid_refs) {
-                // Add up the per-pid total size. Note that if a buffer is mapped
-                // in 2 different processes, the size will be shown as mapped or opened
-                // in both processes. This is intended for visibility.
-                //
-                // If one wants to get the total *unique* dma buffers, they can simply
-                // sum the size of all dma bufs shown by the tool
-                per_pid_size[pid] += buf.size() / 1024;
-                printf("%17d refs |", pid_refs);
-            } else {
-                printf("%22s |", "--");
-            }
-        }
-        dmabuf_total_size += buf.size() / 1024;
-        printf("\n");
-    }
-
-    printf("------------------------------------\n");
-    printf("%-16s  %13" PRIu64 " kB |%16s |", "TOTALS", dmabuf_total_size, "n/a");
-    for (auto pid : pid_set) {
-        printf("%19" PRIu64 " kB |", per_pid_size[pid]);
-    }
-    printf("\n");
-
-    return;
-}
-
-static void PrintDmaBufPerProcess(const std::vector<DmaBuffer>& bufs) {
-    if (bufs.empty()) {
-        printf("dmabuf info not found ¯\\_(ツ)_/¯\n");
-        return;
-    }
-
-    // Create a reverse map from pid to dmabufs
-    std::unordered_map<pid_t, std::set<ino_t>> pid_to_inodes = {};
-    uint64_t total_size = 0;  // Total size of dmabufs in the system
-    uint64_t kernel_rss = 0;  // Total size of dmabufs NOT mapped or opened by a process
-    for (auto& buf : bufs) {
-        for (auto pid : buf.pids()) {
-            pid_to_inodes[pid].insert(buf.inode());
-        }
-        total_size += buf.size();
-        if (buf.fdrefs().empty() && buf.maprefs().empty()) {
-            kernel_rss += buf.size();
-        }
-    }
-    // Create an inode to dmabuf map. We know inodes are unique..
-    std::unordered_map<ino_t, DmaBuffer> inode_to_dmabuf;
-    for (auto buf : bufs) {
-        inode_to_dmabuf[buf.inode()] = buf;
-    }
-
-    uint64_t total_rss = 0, total_pss = 0;
-    for (auto& [pid, inodes] : pid_to_inodes) {
-        uint64_t pss = 0;
-        uint64_t rss = 0;
-
-        printf("%16s:%-5d\n", GetProcessComm(pid).c_str(), pid);
-        printf("%22s %16s %16s %16s %16s\n", "Name", "Rss", "Pss", "nr_procs", "Inode");
-        for (auto& inode : inodes) {
-            DmaBuffer& buf = inode_to_dmabuf[inode];
-            printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16zu %16" PRIuMAX "\n",
-                   buf.name().empty() ? "<unknown>" : buf.name().c_str(), buf.size() / 1024,
-                   buf.Pss() / 1024, buf.pids().size(), static_cast<uintmax_t>(buf.inode()));
-            rss += buf.size();
-            pss += buf.Pss();
-        }
-        printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16s\n", "PROCESS TOTAL", rss / 1024,
-               pss / 1024, "");
-        printf("----------------------\n");
-        total_rss += rss;
-        total_pss += pss;
-    }
-    printf("dmabuf total: %" PRIu64 " kB kernel_rss: %" PRIu64 " kB userspace_rss: %" PRIu64
-           " kB userspace_pss: %" PRIu64 " kB\n ",
-           total_size / 1024, kernel_rss / 1024, total_rss / 1024, total_pss / 1024);
-}
-
-static bool ReadDmaBufs(std::vector<DmaBuffer>* bufs) {
-    bufs->clear();
-
-    if (!ReadDmaBufInfo(bufs)) {
-        fprintf(stderr, "debugfs entry for dmabuf not available, skipping\n");
-        return false;
-    }
-
-    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir);
-    if (!dir) {
-        fprintf(stderr, "Failed to open /proc directory\n");
-        bufs->clear();
-        return false;
-    }
-
-    struct dirent* dent;
-    while ((dent = readdir(dir.get()))) {
-        if (dent->d_type != DT_DIR) continue;
-
-        int pid = atoi(dent->d_name);
-        if (pid == 0) {
-            continue;
-        }
-
-        if (!AppendDmaBufInfo(pid, bufs)) {
-            fprintf(stderr, "Unable to read dmabuf info for pid %d\n", pid);
-            bufs->clear();
-            return false;
-        }
-    }
-
-    return true;
-}
-
-int main(int argc, char* argv[]) {
-    struct option longopts[] = {{"all", no_argument, nullptr, 'a'},
-                                {"help", no_argument, nullptr, 'h'},
-                                {0, 0, nullptr, 0}};
-
-    int opt;
-    bool show_table = false;
-    while ((opt = getopt_long(argc, argv, "ah", longopts, nullptr)) != -1) {
-        switch (opt) {
-            case 'a':
-                show_table = true;
-                break;
-            case 'h':
-                usage(EXIT_SUCCESS);
-            default:
-                usage(EXIT_FAILURE);
-        }
-    }
-
-    pid_t pid = -1;
-    if (optind < argc) {
-        if (show_table) {
-            fprintf(stderr, "Invalid arguments: -a does not need arguments\n");
-            usage(EXIT_FAILURE);
-        }
-        if (optind != (argc - 1)) {
-            fprintf(stderr, "Invalid arguments - only one [PID] argument is allowed\n");
-            usage(EXIT_FAILURE);
-        }
-        pid = atoi(argv[optind]);
-        if (pid == 0) {
-            fprintf(stderr, "Invalid process id %s\n", argv[optind]);
-            usage(EXIT_FAILURE);
-        }
-    }
-
-    std::vector<DmaBuffer> bufs;
-    if (pid != -1) {
-        if (!ReadDmaBufInfo(pid, &bufs)) {
-            fprintf(stderr, "Unable to read dmabuf info for %d\n", pid);
-            exit(EXIT_FAILURE);
-        }
-    } else {
-        if (!ReadDmaBufs(&bufs)) exit(EXIT_FAILURE);
-    }
-
-    // Show the old dmabuf table, inode x process
-    if (show_table) {
-        PrintDmaBufTable(bufs);
-        return 0;
-    }
-
-    PrintDmaBufPerProcess(bufs);
-
-    return 0;
-}
diff --git a/libmeminfo/libmeminfo_benchmark.cpp b/libmeminfo/libmeminfo_benchmark.cpp
deleted file mode 100644
index d88919b..0000000
--- a/libmeminfo/libmeminfo_benchmark.cpp
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * 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.
- */
-
-#include <meminfo/procmeminfo.h>
-#include <meminfo/sysmeminfo.h>
-
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
-
-#include <benchmark/benchmark.h>
-
-using ::android::meminfo::MemUsage;
-using ::android::meminfo::ProcMemInfo;
-using ::android::meminfo::SmapsOrRollupFromFile;
-using ::android::meminfo::SysMemInfo;
-
-enum {
-    MEMINFO_TOTAL,
-    MEMINFO_FREE,
-    MEMINFO_BUFFERS,
-    MEMINFO_CACHED,
-    MEMINFO_SHMEM,
-    MEMINFO_SLAB,
-    MEMINFO_SLAB_RECLAIMABLE,
-    MEMINFO_SLAB_UNRECLAIMABLE,
-    MEMINFO_SWAP_TOTAL,
-    MEMINFO_SWAP_FREE,
-    MEMINFO_ZRAM_TOTAL,
-    MEMINFO_MAPPED,
-    MEMINFO_VMALLOC_USED,
-    MEMINFO_PAGE_TABLES,
-    MEMINFO_KERNEL_STACK,
-    MEMINFO_COUNT
-};
-
-static void get_mem_info(uint64_t mem[], const char* file) {
-    char buffer[4096];
-    unsigned int numFound = 0;
-
-    int fd = open(file, O_RDONLY);
-
-    if (fd < 0) {
-        printf("Unable to open %s: %s\n", file, strerror(errno));
-        return;
-    }
-
-    const int len = read(fd, buffer, sizeof(buffer) - 1);
-    close(fd);
-
-    if (len < 0) {
-        printf("Empty %s\n", file);
-        return;
-    }
-    buffer[len] = 0;
-
-    static const char* const tags[] = {
-            "MemTotal:",     "MemFree:",    "Buffers:",     "Cached:",   "Shmem:", "Slab:",
-            "SReclaimable:", "SUnreclaim:", "SwapTotal:",   "SwapFree:", "ZRam:",  "Mapped:",
-            "VmallocUsed:",  "PageTables:", "KernelStack:", NULL};
-
-    static const int tagsLen[] = {9, 8, 8, 7, 6, 5, 13, 11, 10, 9, 5, 7, 12, 11, 12, 0};
-
-    memset(mem, 0, sizeof(uint64_t) * 15);
-    char* p = buffer;
-    while (*p && (numFound < (sizeof(tagsLen) / sizeof(tagsLen[0])))) {
-        int i = 0;
-        while (tags[i]) {
-            // std::cout << "tag =" << tags[i] << " p = " << std::string(p, tagsLen[i]) <<
-            // std::endl;
-            if (strncmp(p, tags[i], tagsLen[i]) == 0) {
-                p += tagsLen[i];
-                while (*p == ' ') p++;
-                char* num = p;
-                while (*p >= '0' && *p <= '9') p++;
-                if (*p != 0) {
-                    *p = 0;
-                    p++;
-                }
-                mem[i] = atoll(num);
-                numFound++;
-                break;
-            }
-            i++;
-        }
-        while (*p && *p != '\n') {
-            p++;
-        }
-        if (*p) p++;
-    }
-}
-
-static void BM_ReadMemInfo_old(benchmark::State& state) {
-    std::string meminfo = R"meminfo(MemTotal:        3019740 kB
-MemFree:         1809728 kB
-MemAvailable:    2546560 kB
-Buffers:           54736 kB
-Cached:           776052 kB
-SwapCached:            0 kB
-Active:           445856 kB
-Inactive:         459092 kB
-Active(anon):      78492 kB
-Inactive(anon):     2240 kB
-Active(file):     367364 kB
-Inactive(file):   456852 kB
-Unevictable:        3096 kB
-Mlocked:            3096 kB
-SwapTotal:             0 kB
-SwapFree:              0 kB
-Dirty:                32 kB
-Writeback:             0 kB
-AnonPages:         74988 kB
-Mapped:            62624 kB
-Shmem:              4020 kB
-Slab:              86464 kB
-SReclaimable:      44432 kB
-SUnreclaim:        42032 kB
-KernelStack:        4880 kB
-PageTables:         2900 kB
-NFS_Unstable:          0 kB
-Bounce:                0 kB
-WritebackTmp:          0 kB
-CommitLimit:     1509868 kB
-Committed_AS:      80296 kB
-VmallocTotal:   263061440 kB
-VmallocUsed:           0 kB
-VmallocChunk:          0 kB
-AnonHugePages:      6144 kB
-ShmemHugePages:        0 kB
-ShmemPmdMapped:        0 kB
-CmaTotal:         131072 kB
-CmaFree:          130380 kB
-HugePages_Total:       0
-HugePages_Free:        0
-HugePages_Rsvd:        0
-HugePages_Surp:        0
-Hugepagesize:       2048 kB)meminfo";
-
-    TemporaryFile tf;
-    ::android::base::WriteStringToFd(meminfo, tf.fd);
-
-    uint64_t mem[MEMINFO_COUNT];
-    for (auto _ : state) {
-        get_mem_info(mem, tf.path);
-    }
-}
-BENCHMARK(BM_ReadMemInfo_old);
-
-static void BM_ReadMemInfo_new(benchmark::State& state) {
-    std::string meminfo = R"meminfo(MemTotal:        3019740 kB
-MemFree:         1809728 kB
-MemAvailable:    2546560 kB
-Buffers:           54736 kB
-Cached:           776052 kB
-SwapCached:            0 kB
-Active:           445856 kB
-Inactive:         459092 kB
-Active(anon):      78492 kB
-Inactive(anon):     2240 kB
-Active(file):     367364 kB
-Inactive(file):   456852 kB
-Unevictable:        3096 kB
-Mlocked:            3096 kB
-SwapTotal:             0 kB
-SwapFree:              0 kB
-Dirty:                32 kB
-Writeback:             0 kB
-AnonPages:         74988 kB
-Mapped:            62624 kB
-Shmem:              4020 kB
-Slab:              86464 kB
-SReclaimable:      44432 kB
-SUnreclaim:        42032 kB
-KernelStack:        4880 kB
-PageTables:         2900 kB
-NFS_Unstable:          0 kB
-Bounce:                0 kB
-WritebackTmp:          0 kB
-CommitLimit:     1509868 kB
-Committed_AS:      80296 kB
-VmallocTotal:   263061440 kB
-VmallocUsed:           0 kB
-VmallocChunk:          0 kB
-AnonHugePages:      6144 kB
-ShmemHugePages:        0 kB
-ShmemPmdMapped:        0 kB
-CmaTotal:         131072 kB
-CmaFree:          130380 kB
-HugePages_Total:       0
-HugePages_Free:        0
-HugePages_Rsvd:        0
-HugePages_Surp:        0
-Hugepagesize:       2048 kB)meminfo";
-
-    TemporaryFile tf;
-    android::base::WriteStringToFd(meminfo, tf.fd);
-
-    std::string file = std::string(tf.path);
-    std::vector<uint64_t> mem(MEMINFO_COUNT);
-    const std::vector<std::string> tags = {
-            SysMemInfo::kMemTotal,      SysMemInfo::kMemFree,        SysMemInfo::kMemBuffers,
-            SysMemInfo::kMemCached,     SysMemInfo::kMemShmem,       SysMemInfo::kMemSlab,
-            SysMemInfo::kMemSReclaim,   SysMemInfo::kMemSUnreclaim,  SysMemInfo::kMemSwapTotal,
-            SysMemInfo::kMemSwapFree,   SysMemInfo::kMemMapped,      SysMemInfo::kMemVmallocUsed,
-            SysMemInfo::kMemPageTables, SysMemInfo::kMemKernelStack,
-    };
-
-    SysMemInfo smi;
-    for (auto _ : state) {
-        smi.ReadMemInfo(tags, &mem, file);
-    }
-}
-BENCHMARK(BM_ReadMemInfo_new);
-
-static uint64_t get_zram_mem_used(const std::string& zram_dir) {
-    FILE* f = fopen((zram_dir + "mm_stat").c_str(), "r");
-    if (f) {
-        uint64_t mem_used_total = 0;
-
-        int matched = fscanf(f, "%*d %*d %" SCNu64 " %*d %*d %*d %*d", &mem_used_total);
-        if (matched != 1)
-            fprintf(stderr, "warning: failed to parse %s\n", (zram_dir + "mm_stat").c_str());
-
-        fclose(f);
-        return mem_used_total;
-    }
-
-    f = fopen((zram_dir + "mem_used_total").c_str(), "r");
-    if (f) {
-        uint64_t mem_used_total = 0;
-
-        int matched = fscanf(f, "%" SCNu64, &mem_used_total);
-        if (matched != 1)
-            fprintf(stderr, "warning: failed to parse %s\n", (zram_dir + "mem_used_total").c_str());
-
-        fclose(f);
-        return mem_used_total;
-    }
-
-    return 0;
-}
-
-static void BM_ZramTotal_old(benchmark::State& state) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string zram_mmstat_dir = exec_dir + "/testdata1/";
-    for (auto _ : state) {
-        uint64_t zram_total __attribute__((unused)) = get_zram_mem_used(zram_mmstat_dir) / 1024;
-    }
-}
-BENCHMARK(BM_ZramTotal_old);
-
-static void BM_ZramTotal_new(benchmark::State& state) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string zram_mmstat_dir = exec_dir + "/testdata1/";
-    SysMemInfo smi;
-    for (auto _ : state) {
-        uint64_t zram_total __attribute__((unused)) = smi.mem_zram_kb(zram_mmstat_dir);
-    }
-}
-BENCHMARK(BM_ZramTotal_new);
-
-static void BM_MemInfoWithZram_old(benchmark::State& state) {
-    std::string meminfo = R"meminfo(MemTotal:        3019740 kB
-MemFree:         1809728 kB
-MemAvailable:    2546560 kB
-Buffers:           54736 kB
-Cached:           776052 kB
-SwapCached:            0 kB
-Active:           445856 kB
-Inactive:         459092 kB
-Active(anon):      78492 kB
-Inactive(anon):     2240 kB
-Active(file):     367364 kB
-Inactive(file):   456852 kB
-Unevictable:        3096 kB
-Mlocked:            3096 kB
-SwapTotal:             0 kB
-SwapFree:              0 kB
-Dirty:                32 kB
-Writeback:             0 kB
-AnonPages:         74988 kB
-Mapped:            62624 kB
-Shmem:              4020 kB
-Slab:              86464 kB
-SReclaimable:      44432 kB
-SUnreclaim:        42032 kB
-KernelStack:        4880 kB
-PageTables:         2900 kB
-NFS_Unstable:          0 kB
-Bounce:                0 kB
-WritebackTmp:          0 kB
-CommitLimit:     1509868 kB
-Committed_AS:      80296 kB
-VmallocTotal:   263061440 kB
-VmallocUsed:           0 kB
-VmallocChunk:          0 kB
-AnonHugePages:      6144 kB
-ShmemHugePages:        0 kB
-ShmemPmdMapped:        0 kB
-CmaTotal:         131072 kB
-CmaFree:          130380 kB
-HugePages_Total:       0
-HugePages_Free:        0
-HugePages_Rsvd:        0
-HugePages_Surp:        0
-Hugepagesize:       2048 kB)meminfo";
-
-    TemporaryFile tf;
-    ::android::base::WriteStringToFd(meminfo, tf.fd);
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string zram_mmstat_dir = exec_dir + "/testdata1/";
-    uint64_t mem[MEMINFO_COUNT];
-    for (auto _ : state) {
-        get_mem_info(mem, tf.path);
-        mem[MEMINFO_ZRAM_TOTAL] = get_zram_mem_used("/sys/block/zram0/") / 1024;
-        CHECK_EQ(mem[MEMINFO_KERNEL_STACK], 4880u);
-    }
-}
-BENCHMARK(BM_MemInfoWithZram_old);
-
-static void BM_MemInfoWithZram_new(benchmark::State& state) {
-    std::string meminfo = R"meminfo(MemTotal:        3019740 kB
-MemFree:         1809728 kB
-MemAvailable:    2546560 kB
-Buffers:           54736 kB
-Cached:           776052 kB
-SwapCached:            0 kB
-Active:           445856 kB
-Inactive:         459092 kB
-Active(anon):      78492 kB
-Inactive(anon):     2240 kB
-Active(file):     367364 kB
-Inactive(file):   456852 kB
-Unevictable:        3096 kB
-Mlocked:            3096 kB
-SwapTotal:             0 kB
-SwapFree:              0 kB
-Dirty:                32 kB
-Writeback:             0 kB
-AnonPages:         74988 kB
-Mapped:            62624 kB
-Shmem:              4020 kB
-Slab:              86464 kB
-SReclaimable:      44432 kB
-SUnreclaim:        42032 kB
-KernelStack:        4880 kB
-PageTables:         2900 kB
-NFS_Unstable:          0 kB
-Bounce:                0 kB
-WritebackTmp:          0 kB
-CommitLimit:     1509868 kB
-Committed_AS:      80296 kB
-VmallocTotal:   263061440 kB
-VmallocUsed:           0 kB
-VmallocChunk:          0 kB
-AnonHugePages:      6144 kB
-ShmemHugePages:        0 kB
-ShmemPmdMapped:        0 kB
-CmaTotal:         131072 kB
-CmaFree:          130380 kB
-HugePages_Total:       0
-HugePages_Free:        0
-HugePages_Rsvd:        0
-HugePages_Surp:        0
-Hugepagesize:       2048 kB)meminfo";
-
-    TemporaryFile tf;
-    android::base::WriteStringToFd(meminfo, tf.fd);
-
-    std::string file = std::string(tf.path);
-    std::vector<uint64_t> mem(MEMINFO_COUNT);
-    std::vector<std::string> tags(SysMemInfo::kDefaultSysMemInfoTags);
-    auto it = tags.begin();
-    tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
-    SysMemInfo smi;
-
-    for (auto _ : state) {
-        smi.ReadMemInfo(tags, &mem, file);
-        CHECK_EQ(mem[MEMINFO_KERNEL_STACK], 4880u);
-    }
-}
-BENCHMARK(BM_MemInfoWithZram_new);
-
-// Current implementation is in frameworks/base/core/jni/android_os_Debug.cpp.
-// That implementation is still buggy and it skips over vmalloc allocated memory by kernel modules.
-// This is the *fixed* version of the same implementation intended for benchmarking against the new
-// one.
-static uint64_t get_allocated_vmalloc_memory(const std::string& vm_file) {
-    char line[1024];
-
-    uint64_t vmalloc_allocated_size = 0;
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(vm_file.c_str(), "re"), fclose};
-    if (fp == nullptr) {
-        return 0;
-    }
-
-    while (true) {
-        if (fgets(line, 1024, fp.get()) == NULL) {
-            break;
-        }
-
-        // check to see if there are pages mapped in vmalloc area
-        if (!strstr(line, "pages=")) {
-            continue;
-        }
-
-        long nr_pages;
-        if (sscanf(line, "%*x-%*x %*ld %*s pages=%ld", &nr_pages) == 1) {
-            vmalloc_allocated_size += (nr_pages * getpagesize());
-        } else if (sscanf(line, "%*x-%*x %*ld %*s %*s pages=%ld", &nr_pages) == 1) {
-            // The second case is for kernel modules. If allocation comes from the module,
-            // kernel puts an extra string containing the module name before "pages=" in
-            // the line.
-            //    See: https://elixir.bootlin.com/linux/latest/source/kernel/kallsyms.c#L373
-            vmalloc_allocated_size += (nr_pages * getpagesize());
-        }
-    }
-    return vmalloc_allocated_size;
-}
-
-static void BM_VmallocInfo_old_fixed(benchmark::State& state) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string vmallocinfo =
-            ::android::base::StringPrintf("%s/testdata1/vmallocinfo", exec_dir.c_str());
-    for (auto _ : state) {
-        CHECK_EQ(get_allocated_vmalloc_memory(vmallocinfo), 29884416);
-    }
-}
-BENCHMARK(BM_VmallocInfo_old_fixed);
-
-static void BM_VmallocInfo_new(benchmark::State& state) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string vmallocinfo =
-            ::android::base::StringPrintf("%s/testdata1/vmallocinfo", exec_dir.c_str());
-    for (auto _ : state) {
-        CHECK_EQ(::android::meminfo::ReadVmallocInfo(vmallocinfo), 29884416);
-    }
-}
-BENCHMARK(BM_VmallocInfo_new);
-
-// This implementation is picked up as-is from frameworks/base/core/jni/android_os_Debug.cpp
-// and only slightly modified to use std:unique_ptr.
-static bool get_smaps_rollup(const std::string path, MemUsage* rollup) {
-    char lineBuffer[1024];
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
-    if (fp != nullptr) {
-        char* line;
-        while (true) {
-            if (fgets(lineBuffer, sizeof(lineBuffer), fp.get()) == NULL) {
-                break;
-            }
-            line = lineBuffer;
-
-            switch (line[0]) {
-                case 'P':
-                    if (strncmp(line, "Pss:", 4) == 0) {
-                        char* c = line + 4;
-                        while (*c != 0 && (*c < '0' || *c > '9')) {
-                            c++;
-                        }
-                        rollup->pss += atoi(c);
-                    } else if (strncmp(line, "Private_Clean:", 14) == 0 ||
-                               strncmp(line, "Private_Dirty:", 14) == 0) {
-                        char* c = line + 14;
-                        while (*c != 0 && (*c < '0' || *c > '9')) {
-                            c++;
-                        }
-                        rollup->uss += atoi(c);
-                    }
-                    break;
-                case 'R':
-                    if (strncmp(line, "Rss:", 4) == 0) {
-                        char* c = line + 4;
-                        while (*c != 0 && (*c < '0' || *c > '9')) {
-                            c++;
-                        }
-                        rollup->rss += atoi(c);
-                    }
-                    break;
-                case 'S':
-                    if (strncmp(line, "SwapPss:", 8) == 0) {
-                        char* c = line + 8;
-                        long lSwapPss;
-                        while (*c != 0 && (*c < '0' || *c > '9')) {
-                            c++;
-                        }
-                        lSwapPss = atoi(c);
-                        rollup->swap_pss += lSwapPss;
-                    }
-                    break;
-            }
-        }
-    } else {
-        return false;
-    }
-
-    return true;
-}
-
-static void BM_SmapsRollup_old(benchmark::State& state) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string path = ::android::base::StringPrintf("%s/testdata1/smaps", exec_dir.c_str());
-    for (auto _ : state) {
-        MemUsage stats;
-        CHECK_EQ(get_smaps_rollup(path, &stats), true);
-        CHECK_EQ(stats.pss, 108384);
-    }
-}
-BENCHMARK(BM_SmapsRollup_old);
-
-static void BM_SmapsRollup_new(benchmark::State& state) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-    std::string path = ::android::base::StringPrintf("%s/testdata1/smaps", exec_dir.c_str());
-    for (auto _ : state) {
-        MemUsage stats;
-        CHECK_EQ(SmapsOrRollupFromFile(path, &stats), true);
-        CHECK_EQ(stats.pss, 108384);
-    }
-}
-BENCHMARK(BM_SmapsRollup_new);
-
-BENCHMARK_MAIN();
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
deleted file mode 100644
index 5451ca3..0000000
--- a/libmeminfo/libmeminfo_test.cpp
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * 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.
- */
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <gtest/gtest.h>
-
-#include <string>
-#include <vector>
-
-#include <meminfo/pageacct.h>
-#include <meminfo/procmeminfo.h>
-#include <meminfo/sysmeminfo.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
-using namespace std;
-using namespace android::meminfo;
-
-pid_t pid = -1;
-
-TEST(ProcMemInfo, TestWorkingTestReset) {
-    // Expect reset to succeed
-    EXPECT_TRUE(ProcMemInfo::ResetWorkingSet(pid));
-}
-
-TEST(ProcMemInfo, UsageEmpty) {
-    // If we created the object for getting working set,
-    // the usage must be empty
-    ProcMemInfo proc_mem(pid, true);
-    const MemUsage& usage = proc_mem.Usage();
-    EXPECT_EQ(usage.rss, 0);
-    EXPECT_EQ(usage.vss, 0);
-    EXPECT_EQ(usage.pss, 0);
-    EXPECT_EQ(usage.uss, 0);
-    EXPECT_EQ(usage.swap, 0);
-}
-
-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);
-    const MemUsage& wss = proc_mem.Wss();
-    EXPECT_EQ(wss.rss, 0);
-    EXPECT_EQ(wss.vss, 0);
-    EXPECT_EQ(wss.pss, 0);
-    EXPECT_EQ(wss.uss, 0);
-    EXPECT_EQ(wss.swap, 0);
-}
-
-TEST(ProcMemInfo, SwapOffsetsEmpty) {
-    // If we created the object for getting working set,
-    // the swap offsets must be empty
-    ProcMemInfo proc_mem(pid, true);
-    const std::vector<uint16_t>& swap_offsets = proc_mem.SwapOffsets();
-    EXPECT_EQ(swap_offsets.size(), 0);
-}
-
-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);
-    // Second call must return what the first one returned regardless of the pid parameter.
-    // So, deliberately pass invalid pid.
-    EXPECT_EQ(supported, IsSmapsRollupSupported(-1));
-}
-
-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
-Pss:              202052 kB
-Shared_Clean:     158492 kB
-Shared_Dirty:      18928 kB
-Private_Clean:     90472 kB
-Private_Dirty:     64016 kB
-Referenced:       318700 kB
-Anonymous:         81984 kB
-AnonHugePages:         0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:               5344 kB
-SwapPss:             442 kB
-Locked:          1523537 kB)rollup";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(rollup, tf.fd));
-
-    MemUsage stats;
-    ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
-    EXPECT_EQ(stats.rss, 331908);
-    EXPECT_EQ(stats.pss, 202052);
-    EXPECT_EQ(stats.uss, 154488);
-    EXPECT_EQ(stats.private_clean, 90472);
-    EXPECT_EQ(stats.private_dirty, 64016);
-    EXPECT_EQ(stats.swap_pss, 442);
-}
-
-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)]
-Size:               8448 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2652 kB
-Pss:                2652 kB
-Shared_Clean:        840 kB
-Shared_Dirty:         40 kB
-Private_Clean:        84 kB
-Private_Dirty:      2652 kB
-Referenced:         2652 kB
-Anonymous:          2652 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                102 kB
-SwapPss:              70 kB
-Locked:             2652 kB
-VmFlags: rd wr mr mw me ac 
-)smaps";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
-
-    MemUsage stats;
-    ASSERT_EQ(SmapsOrRollupFromFile(tf.path, &stats), true);
-    EXPECT_EQ(stats.rss, 2652);
-    EXPECT_EQ(stats.pss, 2652);
-    EXPECT_EQ(stats.uss, 2736);
-    EXPECT_EQ(stats.private_clean, 84);
-    EXPECT_EQ(stats.private_dirty, 2652);
-    EXPECT_EQ(stats.swap_pss, 70);
-}
-
-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)]
-Size:               8448 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2652 kB
-Pss:                2652 kB
-Shared_Clean:        840 kB
-Shared_Dirty:         40 kB
-Private_Clean:        84 kB
-Private_Dirty:      2652 kB
-Referenced:         2652 kB
-Anonymous:          2652 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                102 kB
-SwapPss:              70 kB
-Locked:             2652 kB
-VmFlags: rd wr mr mw me ac 
-)smaps";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
-
-    uint64_t pss;
-    ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true);
-    EXPECT_EQ(pss, 2652);
-}
-
-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());
-
-    uint64_t pss;
-    ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true);
-    EXPECT_EQ(pss, 19119);
-}
-
-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);
-
-    std::vector<Vma> vmas;
-    auto collect_vmas = [&](const Vma& v) { vmas.push_back(v); };
-    ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas));
-
-    // We should get a total of 6 vmas
-    ASSERT_EQ(vmas.size(), 6);
-
-    // Expect values to be equal to what we have in testdata1/smaps_short
-    // Check for sizes first
-    ASSERT_EQ(vmas[0].usage.vss, 32768);
-    EXPECT_EQ(vmas[1].usage.vss, 11204);
-    EXPECT_EQ(vmas[2].usage.vss, 16896);
-    EXPECT_EQ(vmas[3].usage.vss, 260);
-    EXPECT_EQ(vmas[4].usage.vss, 6060);
-    EXPECT_EQ(vmas[5].usage.vss, 4);
-
-    // Check for names
-    EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
-    EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
-    EXPECT_EQ(vmas[2].name, "[anon:libc_malloc]");
-    EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
-    EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
-    EXPECT_EQ(vmas[5].name, "[vsyscall]");
-
-    EXPECT_EQ(vmas[0].usage.rss, 2048);
-    EXPECT_EQ(vmas[1].usage.rss, 11188);
-    EXPECT_EQ(vmas[2].usage.rss, 15272);
-    EXPECT_EQ(vmas[3].usage.rss, 260);
-    EXPECT_EQ(vmas[4].usage.rss, 4132);
-    EXPECT_EQ(vmas[5].usage.rss, 0);
-
-    EXPECT_EQ(vmas[0].usage.pss, 113);
-    EXPECT_EQ(vmas[1].usage.pss, 2200);
-    EXPECT_EQ(vmas[2].usage.pss, 15272);
-    EXPECT_EQ(vmas[3].usage.pss, 260);
-    EXPECT_EQ(vmas[4].usage.pss, 1274);
-    EXPECT_EQ(vmas[5].usage.pss, 0);
-
-    EXPECT_EQ(vmas[0].usage.uss, 0);
-    EXPECT_EQ(vmas[1].usage.uss, 1660);
-    EXPECT_EQ(vmas[2].usage.uss, 15272);
-    EXPECT_EQ(vmas[3].usage.uss, 260);
-    EXPECT_EQ(vmas[4].usage.uss, 0);
-    EXPECT_EQ(vmas[5].usage.uss, 0);
-
-    EXPECT_EQ(vmas[0].usage.private_clean, 0);
-    EXPECT_EQ(vmas[1].usage.private_clean, 0);
-    EXPECT_EQ(vmas[2].usage.private_clean, 0);
-    EXPECT_EQ(vmas[3].usage.private_clean, 260);
-    EXPECT_EQ(vmas[4].usage.private_clean, 0);
-    EXPECT_EQ(vmas[5].usage.private_clean, 0);
-
-    EXPECT_EQ(vmas[0].usage.private_dirty, 0);
-    EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
-    EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
-    EXPECT_EQ(vmas[3].usage.private_dirty, 0);
-    EXPECT_EQ(vmas[4].usage.private_dirty, 0);
-    EXPECT_EQ(vmas[5].usage.private_dirty, 0);
-
-    EXPECT_EQ(vmas[0].usage.shared_clean, 0);
-    EXPECT_EQ(vmas[1].usage.shared_clean, 80);
-    EXPECT_EQ(vmas[2].usage.shared_clean, 0);
-    EXPECT_EQ(vmas[3].usage.shared_clean, 0);
-    EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
-    EXPECT_EQ(vmas[5].usage.shared_clean, 0);
-
-    EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
-    EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
-    EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
-    EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
-    EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
-    EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
-
-    EXPECT_EQ(vmas[0].usage.swap, 0);
-    EXPECT_EQ(vmas[1].usage.swap, 0);
-    EXPECT_EQ(vmas[2].usage.swap, 0);
-    EXPECT_EQ(vmas[3].usage.swap, 0);
-    EXPECT_EQ(vmas[4].usage.swap, 0);
-    EXPECT_EQ(vmas[5].usage.swap, 0);
-
-    EXPECT_EQ(vmas[0].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[1].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[2].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[3].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[4].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[5].usage.swap_pss, 0);
-}
-
-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(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);
-    auto vmas = proc_mem.Smaps(path);
-
-    ASSERT_FALSE(vmas.empty());
-    // We should get a total of 6 vmas
-    ASSERT_EQ(vmas.size(), 6);
-
-    // Expect values to be equal to what we have in testdata1/smaps_short
-    // Check for sizes first
-    ASSERT_EQ(vmas[0].usage.vss, 32768);
-    EXPECT_EQ(vmas[1].usage.vss, 11204);
-    EXPECT_EQ(vmas[2].usage.vss, 16896);
-    EXPECT_EQ(vmas[3].usage.vss, 260);
-    EXPECT_EQ(vmas[4].usage.vss, 6060);
-    EXPECT_EQ(vmas[5].usage.vss, 4);
-
-    // Check for names
-    EXPECT_EQ(vmas[0].name, "[anon:dalvik-zygote-jit-code-cache]");
-    EXPECT_EQ(vmas[1].name, "/system/framework/x86_64/boot-framework.art");
-    EXPECT_EQ(vmas[2].name, "[anon:libc_malloc]");
-    EXPECT_EQ(vmas[3].name, "/system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex");
-    EXPECT_EQ(vmas[4].name, "/system/lib64/libhwui.so");
-    EXPECT_EQ(vmas[5].name, "[vsyscall]");
-
-    EXPECT_EQ(vmas[0].usage.rss, 2048);
-    EXPECT_EQ(vmas[1].usage.rss, 11188);
-    EXPECT_EQ(vmas[2].usage.rss, 15272);
-    EXPECT_EQ(vmas[3].usage.rss, 260);
-    EXPECT_EQ(vmas[4].usage.rss, 4132);
-    EXPECT_EQ(vmas[5].usage.rss, 0);
-
-    EXPECT_EQ(vmas[0].usage.pss, 113);
-    EXPECT_EQ(vmas[1].usage.pss, 2200);
-    EXPECT_EQ(vmas[2].usage.pss, 15272);
-    EXPECT_EQ(vmas[3].usage.pss, 260);
-    EXPECT_EQ(vmas[4].usage.pss, 1274);
-    EXPECT_EQ(vmas[5].usage.pss, 0);
-
-    EXPECT_EQ(vmas[0].usage.uss, 0);
-    EXPECT_EQ(vmas[1].usage.uss, 1660);
-    EXPECT_EQ(vmas[2].usage.uss, 15272);
-    EXPECT_EQ(vmas[3].usage.uss, 260);
-    EXPECT_EQ(vmas[4].usage.uss, 0);
-    EXPECT_EQ(vmas[5].usage.uss, 0);
-
-    EXPECT_EQ(vmas[0].usage.private_clean, 0);
-    EXPECT_EQ(vmas[1].usage.private_clean, 0);
-    EXPECT_EQ(vmas[2].usage.private_clean, 0);
-    EXPECT_EQ(vmas[3].usage.private_clean, 260);
-    EXPECT_EQ(vmas[4].usage.private_clean, 0);
-    EXPECT_EQ(vmas[5].usage.private_clean, 0);
-
-    EXPECT_EQ(vmas[0].usage.private_dirty, 0);
-    EXPECT_EQ(vmas[1].usage.private_dirty, 1660);
-    EXPECT_EQ(vmas[2].usage.private_dirty, 15272);
-    EXPECT_EQ(vmas[3].usage.private_dirty, 0);
-    EXPECT_EQ(vmas[4].usage.private_dirty, 0);
-    EXPECT_EQ(vmas[5].usage.private_dirty, 0);
-
-    EXPECT_EQ(vmas[0].usage.shared_clean, 0);
-    EXPECT_EQ(vmas[1].usage.shared_clean, 80);
-    EXPECT_EQ(vmas[2].usage.shared_clean, 0);
-    EXPECT_EQ(vmas[3].usage.shared_clean, 0);
-    EXPECT_EQ(vmas[4].usage.shared_clean, 4132);
-    EXPECT_EQ(vmas[5].usage.shared_clean, 0);
-
-    EXPECT_EQ(vmas[0].usage.shared_dirty, 2048);
-    EXPECT_EQ(vmas[1].usage.shared_dirty, 9448);
-    EXPECT_EQ(vmas[2].usage.shared_dirty, 0);
-    EXPECT_EQ(vmas[3].usage.shared_dirty, 0);
-    EXPECT_EQ(vmas[4].usage.shared_dirty, 0);
-    EXPECT_EQ(vmas[5].usage.shared_dirty, 0);
-
-    EXPECT_EQ(vmas[0].usage.swap, 0);
-    EXPECT_EQ(vmas[1].usage.swap, 0);
-    EXPECT_EQ(vmas[2].usage.swap, 0);
-    EXPECT_EQ(vmas[3].usage.swap, 0);
-    EXPECT_EQ(vmas[4].usage.swap, 0);
-    EXPECT_EQ(vmas[5].usage.swap, 0);
-
-    EXPECT_EQ(vmas[0].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[1].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[2].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[3].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[4].usage.swap_pss, 0);
-    EXPECT_EQ(vmas[5].usage.swap_pss, 0);
-}
-
-TEST(SysMemInfo, TestSysMemInfoFile) {
-    std::string meminfo = R"meminfo(MemTotal:        3019740 kB
-MemFree:         1809728 kB
-MemAvailable:    2546560 kB
-Buffers:           54736 kB
-Cached:           776052 kB
-SwapCached:            0 kB
-Active:           445856 kB
-Inactive:         459092 kB
-Active(anon):      78492 kB
-Inactive(anon):     2240 kB
-Active(file):     367364 kB
-Inactive(file):   456852 kB
-Unevictable:        3096 kB
-Mlocked:            3096 kB
-SwapTotal:         32768 kB
-SwapFree:           4096 kB
-Dirty:                32 kB
-Writeback:             0 kB
-AnonPages:         74988 kB
-Mapped:            62624 kB
-Shmem:              4020 kB
-Slab:              86464 kB
-SReclaimable:      44432 kB
-SUnreclaim:        42032 kB
-KernelStack:        4880 kB
-PageTables:         2900 kB
-NFS_Unstable:          0 kB
-Bounce:                0 kB
-WritebackTmp:          0 kB
-CommitLimit:     1509868 kB
-Committed_AS:      80296 kB
-VmallocTotal:   263061440 kB
-VmallocUsed:       65536 kB
-VmallocChunk:          0 kB
-AnonHugePages:      6144 kB
-ShmemHugePages:        0 kB
-ShmemPmdMapped:        0 kB
-CmaTotal:         131072 kB
-CmaFree:          130380 kB
-HugePages_Total:       0
-HugePages_Free:        0
-HugePages_Rsvd:        0
-HugePages_Surp:        0
-Hugepagesize:       2048 kB)meminfo";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
-
-    SysMemInfo mi;
-    ASSERT_TRUE(mi.ReadMemInfo(tf.path));
-    EXPECT_EQ(mi.mem_total_kb(), 3019740);
-    EXPECT_EQ(mi.mem_free_kb(), 1809728);
-    EXPECT_EQ(mi.mem_buffers_kb(), 54736);
-    EXPECT_EQ(mi.mem_cached_kb(), 776052);
-    EXPECT_EQ(mi.mem_shmem_kb(), 4020);
-    EXPECT_EQ(mi.mem_slab_kb(), 86464);
-    EXPECT_EQ(mi.mem_slab_reclaimable_kb(), 44432);
-    EXPECT_EQ(mi.mem_slab_unreclaimable_kb(), 42032);
-    EXPECT_EQ(mi.mem_swap_kb(), 32768);
-    EXPECT_EQ(mi.mem_swap_free_kb(), 4096);
-    EXPECT_EQ(mi.mem_mapped_kb(), 62624);
-    EXPECT_EQ(mi.mem_vmalloc_used_kb(), 65536);
-    EXPECT_EQ(mi.mem_page_tables_kb(), 2900);
-    EXPECT_EQ(mi.mem_kernel_stack_kb(), 4880);
-}
-
-TEST(SysMemInfo, TestEmptyFile) {
-    TemporaryFile tf;
-    std::string empty_string = "";
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(empty_string, tf.fd));
-
-    SysMemInfo mi;
-    EXPECT_TRUE(mi.ReadMemInfo(tf.path));
-    EXPECT_EQ(mi.mem_total_kb(), 0);
-}
-
-TEST(SysMemInfo, TestZramTotal) {
-    std::string exec_dir = ::android::base::GetExecutableDirectory();
-
-    SysMemInfo mi;
-    std::string zram_mmstat_dir = exec_dir + "/testdata1/";
-    EXPECT_EQ(mi.mem_zram_kb(zram_mmstat_dir), 30504);
-
-    std::string zram_memused_dir = exec_dir + "/testdata2/";
-    EXPECT_EQ(mi.mem_zram_kb(zram_memused_dir), 30504);
-}
-
-enum {
-    MEMINFO_TOTAL,
-    MEMINFO_FREE,
-    MEMINFO_BUFFERS,
-    MEMINFO_CACHED,
-    MEMINFO_SHMEM,
-    MEMINFO_SLAB,
-    MEMINFO_SLAB_RECLAIMABLE,
-    MEMINFO_SLAB_UNRECLAIMABLE,
-    MEMINFO_SWAP_TOTAL,
-    MEMINFO_SWAP_FREE,
-    MEMINFO_ZRAM_TOTAL,
-    MEMINFO_MAPPED,
-    MEMINFO_VMALLOC_USED,
-    MEMINFO_PAGE_TABLES,
-    MEMINFO_KERNEL_STACK,
-    MEMINFO_COUNT
-};
-
-TEST(SysMemInfo, TestZramWithTags) {
-    std::string meminfo = R"meminfo(MemTotal:        3019740 kB
-MemFree:         1809728 kB
-MemAvailable:    2546560 kB
-Buffers:           54736 kB
-Cached:           776052 kB
-SwapCached:            0 kB
-Active:           445856 kB
-Inactive:         459092 kB
-Active(anon):      78492 kB
-Inactive(anon):     2240 kB
-Active(file):     367364 kB
-Inactive(file):   456852 kB
-Unevictable:        3096 kB
-Mlocked:            3096 kB
-SwapTotal:         32768 kB
-SwapFree:           4096 kB
-Dirty:                32 kB
-Writeback:             0 kB
-AnonPages:         74988 kB
-Mapped:            62624 kB
-Shmem:              4020 kB
-Slab:              86464 kB
-SReclaimable:      44432 kB
-SUnreclaim:        42032 kB
-KernelStack:        4880 kB
-PageTables:         2900 kB
-NFS_Unstable:          0 kB
-Bounce:                0 kB
-WritebackTmp:          0 kB
-CommitLimit:     1509868 kB
-Committed_AS:      80296 kB
-VmallocTotal:   263061440 kB
-VmallocUsed:       65536 kB
-VmallocChunk:          0 kB
-AnonHugePages:      6144 kB
-ShmemHugePages:        0 kB
-ShmemPmdMapped:        0 kB
-CmaTotal:         131072 kB
-CmaFree:          130380 kB
-HugePages_Total:       0
-HugePages_Free:        0
-HugePages_Rsvd:        0
-HugePages_Surp:        0
-Hugepagesize:       2048 kB)meminfo";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(meminfo, tf.fd));
-    std::string file = std::string(tf.path);
-    std::vector<uint64_t> mem(MEMINFO_COUNT);
-    std::vector<std::string> tags(SysMemInfo::kDefaultSysMemInfoTags);
-    auto it = tags.begin();
-    tags.insert(it + MEMINFO_ZRAM_TOTAL, "Zram:");
-    SysMemInfo mi;
-
-    // Read system memory info
-    EXPECT_TRUE(mi.ReadMemInfo(tags, &mem, file));
-
-    EXPECT_EQ(mem[MEMINFO_TOTAL], 3019740);
-    EXPECT_EQ(mem[MEMINFO_FREE], 1809728);
-    EXPECT_EQ(mem[MEMINFO_BUFFERS], 54736);
-    EXPECT_EQ(mem[MEMINFO_CACHED], 776052);
-    EXPECT_EQ(mem[MEMINFO_SHMEM], 4020);
-    EXPECT_EQ(mem[MEMINFO_SLAB], 86464);
-    EXPECT_EQ(mem[MEMINFO_SLAB_RECLAIMABLE], 44432);
-    EXPECT_EQ(mem[MEMINFO_SLAB_UNRECLAIMABLE], 42032);
-    EXPECT_EQ(mem[MEMINFO_SWAP_TOTAL], 32768);
-    EXPECT_EQ(mem[MEMINFO_SWAP_FREE], 4096);
-    EXPECT_EQ(mem[MEMINFO_MAPPED], 62624);
-    EXPECT_EQ(mem[MEMINFO_VMALLOC_USED], 65536);
-    EXPECT_EQ(mem[MEMINFO_PAGE_TABLES], 2900);
-    EXPECT_EQ(mem[MEMINFO_KERNEL_STACK], 4880);
-}
-
-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
-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap)vmallocinfo";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
-    std::string file = std::string(tf.path);
-
-    EXPECT_EQ(ReadVmallocInfo(file), 0);
-}
-
-TEST(SysMemInfo, TestVmallocInfoKernel) {
-    std::string vmallocinfo =
-            R"vmallocinfo(0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc)vmallocinfo";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
-    std::string file = std::string(tf.path);
-
-    EXPECT_EQ(ReadVmallocInfo(file), getpagesize());
-}
-
-TEST(SysMemInfo, TestVmallocInfoModule) {
-    std::string vmallocinfo =
-            R"vmallocinfo(0x0000000000000000-0x0000000000000000   28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
-    std::string file = std::string(tf.path);
-
-    EXPECT_EQ(ReadVmallocInfo(file), 6 * getpagesize());
-}
-
-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
-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap
-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap
-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc
-0x0000000000000000-0x0000000000000000   28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc)vmallocinfo";
-
-    TemporaryFile tf;
-    ASSERT_TRUE(tf.fd != -1);
-    ASSERT_TRUE(::android::base::WriteStringToFd(vmallocinfo, tf.fd));
-    std::string file = std::string(tf.path);
-
-    EXPECT_EQ(ReadVmallocInfo(file), 7 * getpagesize());
-}
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    ::android::base::InitLogging(argv, android::base::StderrLogger);
-    pid = getpid();
-    return RUN_ALL_TESTS();
-}
diff --git a/libmeminfo/meminfo_private.h b/libmeminfo/meminfo_private.h
deleted file mode 100644
index df5699c..0000000
--- a/libmeminfo/meminfo_private.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <meminfo/meminfo.h>
-#include <meminfo/pageacct.h>
-#include <meminfo/procmeminfo.h>
-#include <meminfo/sysmeminfo.h>
-
-// Macros to do per-page flag manipulation
-#define _BITS(x, offset, bits) (((x) >> (offset)) & ((1LL << (bits)) - 1))
-#define PAGE_PRESENT(x) (_BITS(x, 63, 1))
-#define PAGE_SWAPPED(x) (_BITS(x, 62, 1))
-#define PAGE_SHIFT(x) (_BITS(x, 55, 6))
-#define PAGE_PFN(x) (_BITS(x, 0, 55))
-#define PAGE_SWAP_OFFSET(x) (_BITS(x, 5, 50))
-#define PAGE_SWAP_TYPE(x) (_BITS(x, 0, 5))
diff --git a/libmeminfo/pageacct.cpp b/libmeminfo/pageacct.cpp
deleted file mode 100644
index cb17af8..0000000
--- a/libmeminfo/pageacct.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-
-#include "meminfo_private.h"
-
-using unique_fd = ::android::base::unique_fd;
-
-namespace android {
-namespace meminfo {
-
-static inline off64_t pfn_to_idle_bitmap_offset(uint64_t pfn) {
-    return static_cast<off64_t>((pfn >> 6) << 3);
-}
-
-uint64_t pagesize(void) {
-    static uint64_t pagesize = sysconf(_SC_PAGE_SIZE);
-    return pagesize;
-}
-
-bool PageAcct::InitPageAcct(bool pageidle_enable) {
-    if (pageidle_enable && !PageAcct::KernelHasPageIdle()) {
-        LOG(ERROR) << "Idle page tracking is not supported by the kernel";
-        return false;
-    }
-
-    if (kpagecount_fd_ < 0) {
-        unique_fd count_fd(TEMP_FAILURE_RETRY(open("/proc/kpagecount", O_RDONLY | O_CLOEXEC)));
-        if (count_fd < 0) {
-            PLOG(ERROR) << "Failed to open /proc/kpagecount";
-            return false;
-        }
-        kpagecount_fd_ = std::move(count_fd);
-    }
-
-    if (kpageflags_fd_ < 0) {
-        unique_fd flags_fd(TEMP_FAILURE_RETRY(open("/proc/kpageflags", O_RDONLY | O_CLOEXEC)));
-        if (flags_fd < 0) {
-            PLOG(ERROR) << "Failed to open /proc/kpageflags";
-            return false;
-        }
-        kpageflags_fd_ = std::move(flags_fd);
-    }
-
-    if (pageidle_enable && pageidle_fd_ < 0) {
-        unique_fd idle_fd(
-                TEMP_FAILURE_RETRY(open("/sys/kernel/mm/page_idle/bitmap", O_RDWR | O_CLOEXEC)));
-        if (idle_fd < 0) {
-            PLOG(ERROR) << "Failed to open page idle bitmap";
-            return false;
-        }
-        pageidle_fd_ = std::move(idle_fd);
-    }
-
-    return true;
-}
-
-bool PageAcct::PageFlags(uint64_t pfn, uint64_t* flags) {
-    if (!flags) return false;
-
-    if (kpageflags_fd_ < 0) {
-        if (!InitPageAcct()) return false;
-    }
-
-    if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) !=
-        sizeof(uint64_t)) {
-        PLOG(ERROR) << "Failed to read page flags for page " << pfn;
-        return false;
-    }
-    return true;
-}
-
-bool PageAcct::PageMapCount(uint64_t pfn, uint64_t* mapcount) {
-    if (!mapcount) return false;
-
-    if (kpagecount_fd_ < 0) {
-        if (!InitPageAcct()) return false;
-    }
-
-    if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) !=
-        sizeof(uint64_t)) {
-        PLOG(ERROR) << "Failed to read map count for page " << pfn;
-        return false;
-    }
-    return true;
-}
-
-int PageAcct::IsPageIdle(uint64_t pfn) {
-    if (pageidle_fd_ < 0) {
-        if (!InitPageAcct(true)) return -EOPNOTSUPP;
-    }
-
-    int idle_status = MarkPageIdle(pfn);
-    if (idle_status) return idle_status;
-
-    return GetPageIdle(pfn);
-}
-
-int PageAcct::MarkPageIdle(uint64_t pfn) const {
-    off64_t offset = pfn_to_idle_bitmap_offset(pfn);
-    // set the bit corresponding to page frame
-    uint64_t idle_bits = 1ULL << (pfn % 64);
-
-    if (pwrite64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) < 0) {
-        PLOG(ERROR) << "Failed to write page idle bitmap for page " << pfn;
-        return -errno;
-    }
-
-    return 0;
-}
-
-int PageAcct::GetPageIdle(uint64_t pfn) const {
-    off64_t offset = pfn_to_idle_bitmap_offset(pfn);
-    uint64_t idle_bits;
-
-    if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) != sizeof(uint64_t)) {
-        PLOG(ERROR) << "Failed to read page idle bitmap for page " << pfn;
-        return -errno;
-    }
-
-    return !!(idle_bits & (1ULL << (pfn % 64)));
-}
-
-// Public methods
-bool page_present(uint64_t pagemap_val) {
-    return PAGE_PRESENT(pagemap_val);
-}
-
-bool page_swapped(uint64_t pagemap_val) {
-    return PAGE_SWAPPED(pagemap_val);
-}
-
-uint64_t page_pfn(uint64_t pagemap_val) {
-    return PAGE_PFN(pagemap_val);
-}
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
deleted file mode 100644
index a8b43c1..0000000
--- a/libmeminfo/procmeminfo.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * 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.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <linux/kernel-page-flags.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <atomic>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <procinfo/process_map.h>
-
-#include "meminfo_private.h"
-
-namespace android {
-namespace meminfo {
-
-static void add_mem_usage(MemUsage* to, const MemUsage& from) {
-    to->vss += from.vss;
-    to->rss += from.rss;
-    to->pss += from.pss;
-    to->uss += from.uss;
-
-    to->swap += from.swap;
-
-    to->private_clean += from.private_clean;
-    to->private_dirty += from.private_dirty;
-
-    to->shared_clean += from.shared_clean;
-    to->shared_dirty += from.shared_dirty;
-}
-
-// Returns true if the line was valid smaps stats line false otherwise.
-static bool parse_smaps_field(const char* line, MemUsage* stats) {
-    char field[64];
-    int len;
-    if (sscanf(line, "%63s %n", field, &len) == 1 && *field && field[strlen(field) - 1] == ':') {
-        const char* c = line + len;
-        switch (field[0]) {
-            case 'P':
-                if (strncmp(field, "Pss:", 4) == 0) {
-                    stats->pss = strtoull(c, nullptr, 10);
-                } else if (strncmp(field, "Private_Clean:", 14) == 0) {
-                    uint64_t prcl = strtoull(c, nullptr, 10);
-                    stats->private_clean = prcl;
-                    stats->uss += prcl;
-                } else if (strncmp(field, "Private_Dirty:", 14) == 0) {
-                    uint64_t prdi = strtoull(c, nullptr, 10);
-                    stats->private_dirty = prdi;
-                    stats->uss += prdi;
-                }
-                break;
-            case 'S':
-                if (strncmp(field, "Size:", 5) == 0) {
-                    stats->vss = strtoull(c, nullptr, 10);
-                } else if (strncmp(field, "Shared_Clean:", 13) == 0) {
-                    stats->shared_clean = strtoull(c, nullptr, 10);
-                } else if (strncmp(field, "Shared_Dirty:", 13) == 0) {
-                    stats->shared_dirty = strtoull(c, nullptr, 10);
-                } else if (strncmp(field, "Swap:", 5) == 0) {
-                    stats->swap = strtoull(c, nullptr, 10);
-                } else if (strncmp(field, "SwapPss:", 8) == 0) {
-                    stats->swap_pss = strtoull(c, nullptr, 10);
-                }
-                break;
-            case 'R':
-                if (strncmp(field, "Rss:", 4) == 0) {
-                    stats->rss = strtoull(c, nullptr, 10);
-                }
-                break;
-        }
-        return true;
-    }
-
-    return false;
-}
-
-bool ProcMemInfo::ResetWorkingSet(pid_t pid) {
-    std::string clear_refs_path = ::android::base::StringPrintf("/proc/%d/clear_refs", pid);
-    if (!::android::base::WriteStringToFile("1\n", clear_refs_path)) {
-        PLOG(ERROR) << "Failed to write to " << clear_refs_path;
-        return false;
-    }
-
-    return true;
-}
-
-ProcMemInfo::ProcMemInfo(pid_t pid, bool get_wss, uint64_t pgflags, uint64_t pgflags_mask)
-    : pid_(pid), get_wss_(get_wss), pgflags_(pgflags), pgflags_mask_(pgflags_mask) {}
-
-const std::vector<Vma>& ProcMemInfo::Maps() {
-    if (maps_.empty() && !ReadMaps(get_wss_)) {
-        LOG(ERROR) << "Failed to read maps for Process " << pid_;
-    }
-
-    return maps_;
-}
-
-const std::vector<Vma>& ProcMemInfo::MapsWithPageIdle() {
-    if (maps_.empty() && !ReadMaps(get_wss_, true)) {
-        LOG(ERROR) << "Failed to read maps with page idle for Process " << pid_;
-    }
-
-    return maps_;
-}
-
-const std::vector<Vma>& ProcMemInfo::Smaps(const std::string& path) {
-    if (!maps_.empty()) {
-        return maps_;
-    }
-
-    auto collect_vmas = [&](const Vma& vma) { maps_.emplace_back(vma); };
-    if (path.empty() && !ForEachVma(collect_vmas)) {
-        LOG(ERROR) << "Failed to read smaps for Process " << pid_;
-        maps_.clear();
-    }
-
-    if (!path.empty() && !ForEachVmaFromFile(path, collect_vmas)) {
-        LOG(ERROR) << "Failed to read smaps from file " << path;
-        maps_.clear();
-    }
-
-    return maps_;
-}
-
-const MemUsage& ProcMemInfo::Usage() {
-    if (get_wss_) {
-        LOG(WARNING) << "Trying to read process memory usage for " << pid_
-                     << " using invalid object";
-        return usage_;
-    }
-
-    if (maps_.empty() && !ReadMaps(get_wss_)) {
-        LOG(ERROR) << "Failed to get memory usage for Process " << pid_;
-    }
-
-    return usage_;
-}
-
-const MemUsage& ProcMemInfo::Wss() {
-    if (!get_wss_) {
-        LOG(WARNING) << "Trying to read process working set for " << pid_
-                     << " using invalid object";
-        return usage_;
-    }
-
-    if (maps_.empty() && !ReadMaps(get_wss_)) {
-        LOG(ERROR) << "Failed to get working set for Process " << pid_;
-    }
-
-    return usage_;
-}
-
-bool ProcMemInfo::ForEachVma(const VmaCallback& callback) {
-    std::string path = ::android::base::StringPrintf("/proc/%d/smaps", pid_);
-    return ForEachVmaFromFile(path, callback);
-}
-
-bool ProcMemInfo::SmapsOrRollup(MemUsage* stats) const {
-    std::string path = ::android::base::StringPrintf(
-            "/proc/%d/%s", pid_, IsSmapsRollupSupported(pid_) ? "smaps_rollup" : "smaps");
-    return SmapsOrRollupFromFile(path, stats);
-}
-
-bool ProcMemInfo::SmapsOrRollupPss(uint64_t* pss) const {
-    std::string path = ::android::base::StringPrintf(
-            "/proc/%d/%s", pid_, IsSmapsRollupSupported(pid_) ? "smaps_rollup" : "smaps");
-    return SmapsOrRollupPssFromFile(path, pss);
-}
-
-const std::vector<uint16_t>& ProcMemInfo::SwapOffsets() {
-    if (get_wss_) {
-        LOG(WARNING) << "Trying to read process swap offsets for " << pid_
-                     << " using invalid object";
-        return swap_offsets_;
-    }
-
-    if (maps_.empty() && !ReadMaps(get_wss_)) {
-        LOG(ERROR) << "Failed to get swap offsets for Process " << pid_;
-    }
-
-    return swap_offsets_;
-}
-
-bool ProcMemInfo::PageMap(const Vma& vma, std::vector<uint64_t>* pagemap) {
-    pagemap->clear();
-    std::string pagemap_file = ::android::base::StringPrintf("/proc/%d/pagemap", pid_);
-    ::android::base::unique_fd pagemap_fd(
-            TEMP_FAILURE_RETRY(open(pagemap_file.c_str(), O_RDONLY | O_CLOEXEC)));
-    if (pagemap_fd < 0) {
-        PLOG(ERROR) << "Failed to open " << pagemap_file;
-        return false;
-    }
-
-    uint64_t nr_pages = (vma.end - vma.start) / getpagesize();
-    pagemap->reserve(nr_pages);
-
-    uint64_t idx = vma.start / getpagesize();
-    uint64_t last = idx + nr_pages;
-    uint64_t val;
-    for (; idx < last; idx++) {
-        if (pread64(pagemap_fd, &val, sizeof(uint64_t), idx * sizeof(uint64_t)) < 0) {
-            PLOG(ERROR) << "Failed to read page frames from page map for pid: " << pid_;
-            return false;
-        }
-        pagemap->emplace_back(val);
-    }
-
-    return true;
-}
-
-bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle) {
-    // Each object reads /proc/<pid>/maps only once. This is done to make sure programs that are
-    // running for the lifetime of the system can recycle the objects and don't have to
-    // unnecessarily retain and update this object in memory (which can get significantly large).
-    // E.g. A program that only needs to reset the working set will never all ->Maps(), ->Usage().
-    // E.g. A program that is monitoring smaps_rollup, may never call ->maps(), Usage(), so it
-    // doesn't make sense for us to parse and retain unnecessary memory accounting stats by default.
-    if (!maps_.empty()) return true;
-
-    // parse and read /proc/<pid>/maps
-    std::string maps_file = ::android::base::StringPrintf("/proc/%d/maps", pid_);
-    if (!::android::procinfo::ReadMapFile(
-                maps_file, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t,
-                               const char* name) {
-                    maps_.emplace_back(Vma(start, end, pgoff, flags, name));
-                })) {
-        LOG(ERROR) << "Failed to parse " << maps_file;
-        maps_.clear();
-        return false;
-    }
-
-    std::string pagemap_file = ::android::base::StringPrintf("/proc/%d/pagemap", pid_);
-    ::android::base::unique_fd pagemap_fd(
-            TEMP_FAILURE_RETRY(open(pagemap_file.c_str(), O_RDONLY | O_CLOEXEC)));
-    if (pagemap_fd < 0) {
-        PLOG(ERROR) << "Failed to open " << pagemap_file;
-        return false;
-    }
-
-    for (auto& vma : maps_) {
-        if (!ReadVmaStats(pagemap_fd.get(), vma, get_wss, use_pageidle)) {
-            LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start << "-"
-                       << vma.end << "]";
-            maps_.clear();
-            return false;
-        }
-        add_mem_usage(&usage_, vma.usage);
-    }
-
-    return true;
-}
-
-bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle) {
-    PageAcct& pinfo = PageAcct::Instance();
-    if (get_wss && use_pageidle && !pinfo.InitPageAcct(true)) {
-        LOG(ERROR) << "Failed to init idle page accounting";
-        return false;
-    }
-
-    uint64_t pagesz = getpagesize();
-    size_t num_pages = (vma.end - vma.start) / pagesz;
-    size_t first_page = vma.start / pagesz;
-
-    std::vector<uint64_t> page_cache;
-    size_t cur_page_cache_index = 0;
-    size_t num_in_page_cache = 0;
-    size_t num_leftover_pages = num_pages;
-    for (size_t cur_page = first_page; cur_page < first_page + num_pages; ++cur_page) {
-        if (!get_wss) {
-            vma.usage.vss += pagesz;
-        }
-
-        // Cache page map data.
-        if (cur_page_cache_index == num_in_page_cache) {
-            static constexpr size_t kMaxPages = 2048;
-            num_leftover_pages -= num_in_page_cache;
-            if (num_leftover_pages > kMaxPages) {
-                num_in_page_cache = kMaxPages;
-            } else {
-                num_in_page_cache = num_leftover_pages;
-            }
-            page_cache.resize(num_in_page_cache);
-            size_t total_bytes = page_cache.size() * sizeof(uint64_t);
-            ssize_t bytes = pread64(pagemap_fd, page_cache.data(), total_bytes,
-                                    cur_page * sizeof(uint64_t));
-            if (bytes != total_bytes) {
-                if (bytes == -1) {
-                    PLOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
-                                << cur_page * sizeof(uint64_t);
-                } else {
-                    LOG(ERROR) << "Failed to read page data at offset 0x" << std::hex
-                               << cur_page * sizeof(uint64_t) << std::dec << " read bytes " << bytes
-                               << " expected bytes " << total_bytes;
-                }
-                return false;
-            }
-            cur_page_cache_index = 0;
-        }
-
-        uint64_t page_info = page_cache[cur_page_cache_index++];
-        if (!PAGE_PRESENT(page_info) && !PAGE_SWAPPED(page_info)) continue;
-
-        if (PAGE_SWAPPED(page_info)) {
-            vma.usage.swap += pagesz;
-            swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(page_info));
-            continue;
-        }
-
-        uint64_t page_frame = PAGE_PFN(page_info);
-        uint64_t cur_page_flags;
-        if (!pinfo.PageFlags(page_frame, &cur_page_flags)) {
-            LOG(ERROR) << "Failed to get page flags for " << page_frame << " in process " << pid_;
-            swap_offsets_.clear();
-            return false;
-        }
-
-        // skip unwanted pages from the count
-        if ((cur_page_flags & pgflags_mask_) != pgflags_) continue;
-
-        uint64_t cur_page_counts;
-        if (!pinfo.PageMapCount(page_frame, &cur_page_counts)) {
-            LOG(ERROR) << "Failed to get page count for " << page_frame << " in process " << pid_;
-            swap_offsets_.clear();
-            return false;
-        }
-
-        // Page was unmapped between the presence check at the beginning of the loop and here.
-        if (cur_page_counts == 0) {
-            continue;
-        }
-
-        bool is_dirty = !!(cur_page_flags & (1 << KPF_DIRTY));
-        bool is_private = (cur_page_counts == 1);
-        // Working set
-        if (get_wss) {
-            bool is_referenced = use_pageidle ? (pinfo.IsPageIdle(page_frame) == 1)
-                                              : !!(cur_page_flags & (1 << KPF_REFERENCED));
-            if (!is_referenced) {
-                continue;
-            }
-            // This effectively makes vss = rss for the working set is requested.
-            // The libpagemap implementation returns vss > rss for
-            // working set, which doesn't make sense.
-            vma.usage.vss += pagesz;
-        }
-
-        vma.usage.rss += pagesz;
-        vma.usage.uss += is_private ? pagesz : 0;
-        vma.usage.pss += pagesz / cur_page_counts;
-        if (is_private) {
-            vma.usage.private_dirty += is_dirty ? pagesz : 0;
-            vma.usage.private_clean += is_dirty ? 0 : pagesz;
-        } else {
-            vma.usage.shared_dirty += is_dirty ? pagesz : 0;
-            vma.usage.shared_clean += is_dirty ? 0 : pagesz;
-        }
-    }
-    return true;
-}
-
-// Public APIs
-bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback) {
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
-    if (fp == nullptr) {
-        return false;
-    }
-
-    char* line = nullptr;
-    bool parsing_vma = false;
-    ssize_t line_len;
-    size_t line_alloc = 0;
-    Vma vma;
-    while ((line_len = getline(&line, &line_alloc, fp.get())) > 0) {
-        // Make sure the line buffer terminates like a C string for ReadMapFile
-        line[line_len] = '\0';
-
-        if (parsing_vma) {
-            if (parse_smaps_field(line, &vma.usage)) {
-                // This was a stats field
-                continue;
-            }
-
-            // Done collecting stats, make the call back
-            callback(vma);
-            parsing_vma = false;
-        }
-
-        vma.clear();
-        // If it has, we are looking for the vma stats
-        // 00400000-00409000 r-xp 00000000 fc:00 426998  /usr/lib/gvfs/gvfsd-http
-        if (!::android::procinfo::ReadMapFileContent(
-                    line, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t,
-                              const char* name) {
-                        vma.start = start;
-                        vma.end = end;
-                        vma.flags = flags;
-                        vma.offset = pgoff;
-                        vma.name = name;
-                    })) {
-            LOG(ERROR) << "Failed to parse " << path;
-            return false;
-        }
-        parsing_vma = true;
-    }
-
-    // free getline() managed buffer
-    free(line);
-
-    if (parsing_vma) {
-        callback(vma);
-    }
-
-    return true;
-}
-
-enum smaps_rollup_support { UNTRIED, SUPPORTED, UNSUPPORTED };
-
-static std::atomic<smaps_rollup_support> g_rollup_support = UNTRIED;
-
-bool IsSmapsRollupSupported(pid_t pid) {
-    // Similar to OpenSmapsOrRollup checks from android_os_Debug.cpp, except
-    // the method only checks if rollup is supported and returns the status
-    // right away.
-    enum smaps_rollup_support rollup_support = g_rollup_support.load(std::memory_order_relaxed);
-    if (rollup_support != UNTRIED) {
-        return rollup_support == SUPPORTED;
-    }
-    std::string rollup_file = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
-    if (access(rollup_file.c_str(), F_OK | R_OK)) {
-        // No check for errno = ENOENT necessary here. The caller MUST fallback to
-        // using /proc/<pid>/smaps instead anyway.
-        g_rollup_support.store(UNSUPPORTED, std::memory_order_relaxed);
-        return false;
-    }
-
-    g_rollup_support.store(SUPPORTED, std::memory_order_relaxed);
-    LOG(INFO) << "Using smaps_rollup for pss collection";
-    return true;
-}
-
-bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats) {
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
-    if (fp == nullptr) {
-        return false;
-    }
-
-    char* line = nullptr;
-    size_t line_alloc = 0;
-    stats->clear();
-    while (getline(&line, &line_alloc, fp.get()) > 0) {
-        switch (line[0]) {
-            case 'P':
-                if (strncmp(line, "Pss:", 4) == 0) {
-                    char* c = line + 4;
-                    stats->pss += strtoull(c, nullptr, 10);
-                } else if (strncmp(line, "Private_Clean:", 14) == 0) {
-                    char* c = line + 14;
-                    uint64_t prcl = strtoull(c, nullptr, 10);
-                    stats->private_clean += prcl;
-                    stats->uss += prcl;
-                } else if (strncmp(line, "Private_Dirty:", 14) == 0) {
-                    char* c = line + 14;
-                    uint64_t prdi = strtoull(c, nullptr, 10);
-                    stats->private_dirty += prdi;
-                    stats->uss += prdi;
-                }
-                break;
-            case 'R':
-                if (strncmp(line, "Rss:", 4) == 0) {
-                    char* c = line + 4;
-                    stats->rss += strtoull(c, nullptr, 10);
-                }
-                break;
-            case 'S':
-                if (strncmp(line, "SwapPss:", 8) == 0) {
-                    char* c = line + 8;
-                    stats->swap_pss += strtoull(c, nullptr, 10);
-                }
-                break;
-        }
-    }
-
-    // free getline() managed buffer
-    free(line);
-    return true;
-}
-
-bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss) {
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
-    if (fp == nullptr) {
-        return false;
-    }
-    *pss = 0;
-    char* line = nullptr;
-    size_t line_alloc = 0;
-    while (getline(&line, &line_alloc, fp.get()) > 0) {
-        uint64_t v;
-        if (sscanf(line, "Pss: %" SCNu64 " kB", &v) == 1) {
-            *pss += v;
-        }
-    }
-
-    // free getline() managed buffer
-    free(line);
-    return true;
-}
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/sysmeminfo.cpp b/libmeminfo/sysmeminfo.cpp
deleted file mode 100644
index 5cfa6c3..0000000
--- a/libmeminfo/sysmeminfo.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * 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.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <cctype>
-#include <cstdio>
-#include <fstream>
-#include <iterator>
-#include <sstream>
-#include <string>
-#include <utility>
-#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 <android-base/unique_fd.h>
-
-#include "meminfo_private.h"
-
-namespace android {
-namespace meminfo {
-
-const std::vector<std::string> SysMemInfo::kDefaultSysMemInfoTags = {
-        SysMemInfo::kMemTotal,      SysMemInfo::kMemFree,        SysMemInfo::kMemBuffers,
-        SysMemInfo::kMemCached,     SysMemInfo::kMemShmem,       SysMemInfo::kMemSlab,
-        SysMemInfo::kMemSReclaim,   SysMemInfo::kMemSUnreclaim,  SysMemInfo::kMemSwapTotal,
-        SysMemInfo::kMemSwapFree,   SysMemInfo::kMemMapped,      SysMemInfo::kMemVmallocUsed,
-        SysMemInfo::kMemPageTables, SysMemInfo::kMemKernelStack,
-};
-
-bool SysMemInfo::ReadMemInfo(const std::string& path) {
-    return ReadMemInfo(SysMemInfo::kDefaultSysMemInfoTags, path,
-                       [&](const std::string& tag, uint64_t val) { mem_in_kb_[tag] = val; });
-}
-
-bool SysMemInfo::ReadMemInfo(std::vector<uint64_t>* out, const std::string& path) {
-    return ReadMemInfo(SysMemInfo::kDefaultSysMemInfoTags, out, path);
-}
-
-bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, std::vector<uint64_t>* out,
-                             const std::string& path) {
-    out->clear();
-    out->resize(tags.size());
-
-    return ReadMemInfo(tags, path, [&]([[maybe_unused]] const std::string& tag, uint64_t val) {
-        auto it = std::find(tags.begin(), tags.end(), tag);
-        if (it == tags.end()) {
-            LOG(ERROR) << "Tried to store invalid tag: " << tag;
-            return;
-        }
-        auto index = std::distance(tags.begin(), it);
-        // store the values in the same order as the tags
-        out->at(index) = val;
-    });
-}
-
-uint64_t SysMemInfo::ReadVmallocInfo() {
-    return ::android::meminfo::ReadVmallocInfo();
-}
-
-// TODO: Delete this function if it can't match up with the c-like implementation below.
-// Currently, this added about 50 % extra overhead on hikey.
-#if 0
-bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::string& path) {
-    std::string buffer;
-    if (!::android::base::ReadFileToString(path, &buffer)) {
-        PLOG(ERROR) << "Failed to read : " << path;
-        return false;
-    }
-
-    uint32_t total_found = 0;
-    for (auto s = buffer.begin(); s < buffer.end() && total_found < tags.size();) {
-        for (auto& tag : tags) {
-            if (tag == std::string(s, s + tag.size())) {
-                s += tag.size();
-                while (isspace(*s)) s++;
-                auto num_start = s;
-                while (std::isdigit(*s)) s++;
-
-                std::string number(num_start, num_start + (s - num_start));
-                if (!::android::base::ParseUint(number, &mem_in_kb_[tag])) {
-                    LOG(ERROR) << "Failed to parse uint";
-                    return false;
-                }
-                total_found++;
-                break;
-            }
-        }
-        while (s < buffer.end() && *s != '\n') s++;
-        if (s < buffer.end()) s++;
-    }
-
-    return true;
-}
-
-#else
-bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::string& path,
-                             std::function<void(const std::string&, uint64_t)> store_val) {
-    char buffer[4096];
-    int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
-    if (fd < 0) {
-        PLOG(ERROR) << "Failed to open file :" << path;
-        return false;
-    }
-
-    const int len = read(fd, buffer, sizeof(buffer) - 1);
-    close(fd);
-    if (len < 0) {
-        return false;
-    }
-
-    buffer[len] = '\0';
-    char* p = buffer;
-    uint32_t found = 0;
-    uint32_t lineno = 0;
-    bool zram_tag_found = false;
-    while (*p && found < tags.size()) {
-        for (auto& tag : tags) {
-            // Special case for "Zram:" tag that android_os_Debug and friends look
-            // up along with the rest of the numbers from /proc/meminfo
-            if (!zram_tag_found && tag == "Zram:") {
-                store_val(tag, mem_zram_kb());
-                zram_tag_found = true;
-                found++;
-                continue;
-            }
-
-            if (strncmp(p, tag.c_str(), tag.size()) == 0) {
-                p += tag.size();
-                while (*p == ' ') p++;
-                char* endptr = nullptr;
-                uint64_t val = strtoull(p, &endptr, 10);
-                if (p == endptr) {
-                    PLOG(ERROR) << "Failed to parse line:" << lineno + 1 << " in file: " << path;
-                    return false;
-                }
-                store_val(tag, val);
-                p = endptr;
-                found++;
-                break;
-            }
-        }
-
-        while (*p && *p != '\n') {
-            p++;
-        }
-        if (*p) p++;
-        lineno++;
-    }
-
-    return true;
-}
-#endif
-
-uint64_t SysMemInfo::mem_zram_kb(const std::string& zram_dev) {
-    uint64_t mem_zram_total = 0;
-    if (!zram_dev.empty()) {
-        if (!MemZramDevice(zram_dev, &mem_zram_total)) {
-            return 0;
-        }
-        return mem_zram_total / 1024;
-    }
-
-    constexpr uint32_t kMaxZramDevices = 256;
-    for (uint32_t i = 0; i < kMaxZramDevices; i++) {
-        std::string zram_dev = ::android::base::StringPrintf("/sys/block/zram%u/", i);
-        if (access(zram_dev.c_str(), F_OK)) {
-            // We assume zram devices appear in range 0-255 and appear always in sequence
-            // under /sys/block. So, stop looking for them once we find one is missing.
-            break;
-        }
-
-        uint64_t mem_zram_dev;
-        if (!MemZramDevice(zram_dev, &mem_zram_dev)) {
-            return 0;
-        }
-
-        mem_zram_total += mem_zram_dev;
-    }
-
-    return mem_zram_total / 1024;
-}
-
-bool SysMemInfo::MemZramDevice(const std::string& zram_dev, uint64_t* mem_zram_dev) {
-    std::string mmstat = ::android::base::StringPrintf("%s/%s", zram_dev.c_str(), "mm_stat");
-    auto mmstat_fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(mmstat.c_str(), "re"), fclose};
-    if (mmstat_fp != nullptr) {
-        // only if we do have mmstat, use it. Otherwise, fall through to trying out the old
-        // 'mem_used_total'
-        if (fscanf(mmstat_fp.get(), "%*" SCNu64 " %*" SCNu64 " %" SCNu64, mem_zram_dev) != 1) {
-            PLOG(ERROR) << "Malformed mm_stat file in: " << zram_dev;
-            return false;
-        }
-        return true;
-    }
-
-    std::string content;
-    if (::android::base::ReadFileToString(zram_dev + "mem_used_total", &content)) {
-        *mem_zram_dev = strtoull(content.c_str(), NULL, 10);
-        if (*mem_zram_dev == ULLONG_MAX) {
-            PLOG(ERROR) << "Malformed mem_used_total file for zram dev: " << zram_dev
-                        << " content: " << content;
-            return false;
-        }
-
-        return true;
-    }
-
-    LOG(ERROR) << "Can't find memory status under: " << zram_dev;
-    return false;
-}
-
-// Public methods
-uint64_t ReadVmallocInfo(const std::string& path) {
-    uint64_t vmalloc_total = 0;
-    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
-    if (fp == nullptr) {
-        return vmalloc_total;
-    }
-
-    char* line = nullptr;
-    size_t line_alloc = 0;
-    while (getline(&line, &line_alloc, fp.get()) > 0) {
-        // We are looking for lines like
-        //
-        // 0x0000000000000000-0x0000000000000000   12288 drm_property_create_blob+0x44/0xec pages=2 vmalloc
-        // 0x0000000000000000-0x0000000000000000    8192 wlan_logging_sock_init_svc+0xf8/0x4f0 [wlan] pages=1 vmalloc
-        //
-        // Notice that if the caller is coming from a module, the kernel prints and extra
-        // "[module_name]" after the address and the symbol of the call site. This means we can't
-        // use the old sscanf() method of getting the # of pages.
-        char* p_start = strstr(line, "pages=");
-        if (p_start == nullptr) {
-            // we didn't find anything
-            continue;
-        }
-
-        uint64_t nr_pages;
-        if (sscanf(p_start, "pages=%" SCNu64 "", &nr_pages) == 1) {
-            vmalloc_total += (nr_pages * getpagesize());
-        }
-    }
-
-    free(line);
-
-    return vmalloc_total;
-}
-
-}  // namespace meminfo
-}  // namespace android
diff --git a/libmeminfo/testdata1/mm_stat b/libmeminfo/testdata1/mm_stat
deleted file mode 100644
index 32b325f..0000000
--- a/libmeminfo/testdata1/mm_stat
+++ /dev/null
@@ -1 +0,0 @@
- 145674240 26801454 31236096        0 45772800     3042     1887      517
diff --git a/libmeminfo/testdata1/showmap_test.sh b/libmeminfo/testdata1/showmap_test.sh
deleted file mode 100755
index 8ee713e..0000000
--- a/libmeminfo/testdata1/showmap_test.sh
+++ /dev/null
@@ -1,86 +0,0 @@
-#! /system/bin/sh
-
-TESTDATA_PATH=/data/nativetest64/libmeminfo_test/testdata1
-SMAPS=$TESTDATA_PATH/smaps
-OUT1=$TMPDIR/1.txt
-OUT2=$TMPDIR/2.txt
-
-showmap -f $SMAPS > $OUT1
-showmap2 -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -f <smaps>";
-else
-    echo "pass: showmap -f <smaps>"
-fi
-
-showmap -q -f $SMAPS > $OUT1
-showmap2 -q -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -q -f <smaps>";
-else
-    echo "pass: showmap -q -f <smaps>"
-fi
-
-showmap -v -f $SMAPS > $OUT1
-showmap2 -v -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -v -f <smaps>";
-else
-    echo "pass: showmap -v -f <smaps>"
-fi
-
-showmap -a -f $SMAPS > $OUT1
-showmap2 -a -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -a -f <smaps>";
-else
-    echo "pass: showmap -a -f <smaps>"
-fi
-
-# Note that all tests from here down that have the option
-# '-a' added to the command are expected to fail as
-# 'showmap2' actually fixes the 64-bit address truncating
-# that was already happening with showmap
-showmap -a -t -f $SMAPS > $OUT1
-showmap2 -a -t -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -a -t -f <smaps>";
-else
-    echo "pass: showmap -a -t -f <smaps>"
-fi
-
-showmap -a -t -v -f $SMAPS > $OUT1
-showmap2 -a -t -v -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -a -t -v -f <smaps>";
-else
-    echo "pass: showmap -a -t -v -f <smaps>"
-fi
-
-# Note: This test again is expected to fail as the new
-# showmap fixes an issue with -t where the tool was only
-# showing maps with private dirty pages. The '-t' option was however
-# supposed to show all maps that have 'private' pages, clean or dirty.
-showmap -t -f $SMAPS > $OUT1
-showmap2 -t -f $SMAPS > $OUT2
-diff $OUT1 $OUT2 > /dev/null
-ret=$?
-if [[ $ret != 0 ]]; then
-    echo "fail: showmap -t -f <smaps>";
-else
-    echo "pass: showmap -t -f <smaps>"
-fi
-
-
diff --git a/libmeminfo/testdata1/smaps b/libmeminfo/testdata1/smaps
deleted file mode 100644
index 23aa2af..0000000
--- a/libmeminfo/testdata1/smaps
+++ /dev/null
@@ -1,56297 +0,0 @@
-12c00000-13440000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:               8448 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2652 kB
-Pss:                2652 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      2652 kB
-Referenced:         2652 kB
-Anonymous:          2652 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2652 kB
-VmFlags: rd wr mr mw me ac 
-13440000-13500000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13500000-13540000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                 256 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       256 kB
-Referenced:          256 kB
-Anonymous:           256 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd wr mr mw me ac 
-13540000-137c0000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:               2560 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-137c0000-13880000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 740 kB
-Pss:                 740 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       740 kB
-Referenced:          740 kB
-Anonymous:           740 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              740 kB
-VmFlags: rd wr mr mw me ac 
-13880000-13900000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                512 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13900000-13940000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                 256 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       256 kB
-Referenced:          256 kB
-Anonymous:           256 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd wr mr mw me ac 
-13940000-13a40000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13a40000-13a80000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                 256 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       256 kB
-Referenced:          256 kB
-Anonymous:           256 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd wr mr mw me ac 
-13a80000-13b40000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13b40000-13b80000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                 256 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       256 kB
-Referenced:          256 kB
-Anonymous:           256 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd wr mr mw me ac 
-13b80000-13bc0000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13bc0000-13d80000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:               1792 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1792 kB
-Pss:                1792 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      1792 kB
-Referenced:         1792 kB
-Anonymous:          1792 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1792 kB
-VmFlags: rd wr mr mw me ac 
-13d80000-13dc0000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13dc0000-13e00000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                 256 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       256 kB
-Referenced:          256 kB
-Anonymous:           256 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd wr mr mw me ac 
-13e00000-13e40000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13e40000-13e80000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                 256 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       256 kB
-Referenced:          256 kB
-Anonymous:           256 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd wr mr mw me ac 
-13e80000-13ec0000 ---p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-13ec0000-52c00000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
-Name:           [anon:dalvik-main space (region space)]
-Size:            1029376 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 768 kB
-Pss:                 768 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       768 kB
-Referenced:          768 kB
-Anonymous:           768 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              768 kB
-VmFlags: rd wr mr mw me ac 
-52c00000-54c00000 rw-p 00000000 00:00 0                                  [anon:dalvik-zygote-data-code-cache]
-Name:           [anon:dalvik-zygote-data-code-cache]
-Size:              32768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2048 kB
-Pss:                 512 kB
-Shared_Clean:          0 kB
-Shared_Dirty:       2048 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2048 kB
-Anonymous:          2048 kB
-AnonHugePages:      2048 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              512 kB
-VmFlags: rd wr mr mw me ac 
-54c00000-56c00000 r-xp 00000000 00:00 0                                  [anon:dalvik-zygote-jit-code-cache]
-Name:           [anon:dalvik-zygote-jit-code-cache]
-Size:              32768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2048 kB
-Pss:                 113 kB
-Shared_Clean:          0 kB
-Shared_Dirty:       2048 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2048 kB
-Anonymous:          2048 kB
-AnonHugePages:      2048 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              113 kB
-VmFlags: rd ex mr mw me ac 
-56c00000-56c05000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-56c05000-56c37000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                200 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 200 kB
-Pss:                  11 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        200 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:           200 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               11 kB
-VmFlags: rd wr mr mw me ac 
-56c37000-56c45000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-56c45000-56c4e000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         36 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            36 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd wr mr mw me ac 
-56c52000-56c5c000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         40 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            40 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr mr mw me ac 
-56c5c000-56c61000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me ac 
-56c63000-56c6e000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         44 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            44 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr mr mw me ac 
-56c6e000-56c77000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-56c79000-56d05000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                560 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 560 kB
-Pss:                  31 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        560 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:           560 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               31 kB
-VmFlags: rd wr mr mw me ac 
-56d05000-56d0e000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-56d10000-56d16000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd wr mr mw me ac 
-56d1d000-56d21000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-56d21000-58d21000 rw-s 00000000 00:05 9572                               /memfd:/jit-cache (deleted)
-Size:              32768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr sh mr mw me ms 
-58d21000-5ad21000 r-xs 02000000 00:05 9572                               /memfd:/jit-cache (deleted)
-Size:              32768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex sh mr mw me ms 
-5ad21000-5ae6f000 rw-p 00000000 00:00 0                                  [anon:dalvik-/system/framework/oat/x86_64/services.art]
-Name:           [anon:dalvik-/system/framework/oat/x86_64/services.art]
-Size:               1336 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1336 kB
-Pss:                1336 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      1336 kB
-Referenced:         1336 kB
-Anonymous:          1336 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1336 kB
-VmFlags: rd wr mr mw me ac 
-5ae6f000-5aeb5000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                280 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 112 kB
-Pss:                 112 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       112 kB
-Referenced:          112 kB
-Anonymous:           112 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              112 kB
-VmFlags: rd wr mr mw me ac 
-5aeb6000-5aebf000 rw-p 00000000 00:00 0                                  [anon:dalvik-large object space allocation]
-Name:           [anon:dalvik-large object space allocation]
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-6fc4d000-6ff1e000 rw-p 00000000 fe:00 3184                               /system/framework/x86_64/boot.art
-Size:               2884 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2884 kB
-Pss:                 472 kB
-Shared_Clean:          4 kB
-Shared_Dirty:       2552 kB
-Private_Clean:         0 kB
-Private_Dirty:       328 kB
-Referenced:         2728 kB
-Anonymous:          2880 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              472 kB
-VmFlags: rd wr mr mw me ac 
-6ff1e000-70050000 rw-p 00000000 fe:00 3174                               /system/framework/x86_64/boot-core-libart.art
-Size:               1224 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1212 kB
-Pss:                 234 kB
-Shared_Clean:          4 kB
-Shared_Dirty:       1032 kB
-Private_Clean:         0 kB
-Private_Dirty:       176 kB
-Referenced:         1092 kB
-Anonymous:          1208 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              234 kB
-VmFlags: rd wr mr mw me ac 
-70050000-70051000 rw-p 00000000 fe:00 3197                               /system/framework/x86_64/boot-core-simple.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70051000-70091000 rw-p 00000000 fe:00 3168                               /system/framework/x86_64/boot-conscrypt.art
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                  89 kB
-Shared_Clean:          4 kB
-Shared_Dirty:        172 kB
-Private_Clean:         0 kB
-Private_Dirty:        80 kB
-Referenced:          236 kB
-Anonymous:           252 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               89 kB
-VmFlags: rd wr mr mw me ac 
-70091000-700ce000 rw-p 00000000 fe:00 3166                               /system/framework/x86_64/boot-okhttp.art
-Size:                244 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 240 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        224 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:          200 kB
-Anonymous:           240 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd wr mr mw me ac 
-700ce000-70136000 rw-p 00000000 fe:00 3175                               /system/framework/x86_64/boot-bouncycastle.art
-Size:                416 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 412 kB
-Pss:                  22 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        412 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          236 kB
-Anonymous:           412 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               22 kB
-VmFlags: rd wr mr mw me ac 
-70136000-7019d000 rw-p 00000000 fe:00 3167                               /system/framework/x86_64/boot-apache-xml.art
-Size:                412 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 408 kB
-Pss:                  22 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        408 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          276 kB
-Anonymous:           408 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               22 kB
-VmFlags: rd wr mr mw me ac 
-7019d000-701ea000 rw-p 00000000 fe:00 3196                               /system/framework/x86_64/boot-ext.art
-Size:                308 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 308 kB
-Pss:                  20 kB
-Shared_Clean:          4 kB
-Shared_Dirty:        300 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:          256 kB
-Anonymous:           304 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me ac 
-701ea000-70cdb000 rw-p 00000000 fe:00 3165                               /system/framework/x86_64/boot-framework.art
-Size:              11204 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               11188 kB
-Pss:                2200 kB
-Shared_Clean:         80 kB
-Shared_Dirty:       9448 kB
-Private_Clean:         0 kB
-Private_Dirty:      1660 kB
-Referenced:         9892 kB
-Anonymous:         11108 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2200 kB
-VmFlags: rd wr mr mw me ac 
-70cdb000-70df1000 rw-p 00000000 fe:00 3178                               /system/framework/x86_64/boot-telephony-common.art
-Size:               1112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1112 kB
-Pss:                  63 kB
-Shared_Clean:          4 kB
-Shared_Dirty:       1108 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          524 kB
-Anonymous:          1108 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               63 kB
-VmFlags: rd wr mr mw me ac 
-70df1000-70e02000 rw-p 00000000 fe:00 3198                               /system/framework/x86_64/boot-voip-common.art
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                   3 kB
-Shared_Clean:          4 kB
-Shared_Dirty:         64 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:            64 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd wr mr mw me ac 
-70e02000-70e1e000 rw-p 00000000 fe:00 3176                               /system/framework/x86_64/boot-ims-common.art
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 112 kB
-Pss:                   6 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        112 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:           112 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd wr mr mw me ac 
-70e1e000-70e20000 rw-p 00000000 fe:00 3201                               /system/framework/x86_64/boot-framework-oahl-backward-compatibility.art
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70e20000-70e26000 rw-p 00000000 fe:00 3170                               /system/framework/x86_64/boot-android.test.base.impl.art
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd wr mr mw me ac 
-70e26000-70f04000 r--p 00000000 fe:00 3199                               /system/framework/x86_64/boot.oat
-Size:                888 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 856 kB
-Pss:                  66 kB
-Shared_Clean:        856 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          856 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               66 kB
-VmFlags: rd mr mw me 
-70f04000-71279000 r-xp 000de000 fe:00 3199                               /system/framework/x86_64/boot.oat
-Size:               3540 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                3476 kB
-Pss:                 308 kB
-Shared_Clean:       3412 kB
-Shared_Dirty:          0 kB
-Private_Clean:        64 kB
-Private_Dirty:         0 kB
-Referenced:         3476 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              308 kB
-VmFlags: rd ex mr mw me 
-71279000-7127a000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7127a000-71700000 r--s 00000000 fe:00 3396                               /system/framework/boot.vdex
-Size:               4632 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                3592 kB
-Pss:                 423 kB
-Shared_Clean:       3592 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         3592 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              423 kB
-VmFlags: rd mr me ms 
-71700000-71701000 r--p 00453000 fe:00 3199                               /system/framework/x86_64/boot.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-71701000-71702000 rw-p 00454000 fe:00 3199                               /system/framework/x86_64/boot.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71702000-7175d000 r--p 00000000 fe:00 3181                               /system/framework/x86_64/boot-core-libart.oat
-Size:                364 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 356 kB
-Pss:                  20 kB
-Shared_Clean:        356 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          356 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me 
-7175d000-718b6000 r-xp 0005b000 fe:00 3181                               /system/framework/x86_64/boot-core-libart.oat
-Size:               1380 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1360 kB
-Pss:                 127 kB
-Shared_Clean:       1360 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         1360 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              127 kB
-VmFlags: rd ex mr mw me 
-718b6000-718b7000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-718b7000-71bcb000 r--s 00000000 fe:00 3146                               /system/framework/boot-core-libart.vdex
-Size:               3152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2228 kB
-Pss:                 238 kB
-Shared_Clean:       2228 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2228 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              238 kB
-VmFlags: rd mr me ms 
-71bcb000-71bcc000 r--p 001b4000 fe:00 3181                               /system/framework/x86_64/boot-core-libart.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-71bcc000-71bcd000 rw-p 001b5000 fe:00 3181                               /system/framework/x86_64/boot-core-libart.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71bcd000-71bcf000 r--p 00000000 fe:00 3182                               /system/framework/x86_64/boot-core-simple.oat
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-71bcf000-71bd0000 r-xp 00002000 fe:00 3182                               /system/framework/x86_64/boot-core-simple.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-71bd0000-71bd1000 r--s 00000000 fe:00 3216                               /system/framework/boot-core-simple.vdex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-71bd1000-71bd2000 r--p 00003000 fe:00 3182                               /system/framework/x86_64/boot-core-simple.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-71bd2000-71bd3000 rw-p 00004000 fe:00 3182                               /system/framework/x86_64/boot-core-simple.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71bd3000-71be2000 r--p 00000000 fe:00 3205                               /system/framework/x86_64/boot-conscrypt.oat
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   3 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-71be2000-71c12000 r-xp 0000f000 fe:00 3205                               /system/framework/x86_64/boot-conscrypt.oat
-Size:                192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 184 kB
-Pss:                  25 kB
-Shared_Clean:        184 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          184 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               25 kB
-VmFlags: rd ex mr mw me 
-71c12000-71c13000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-71c13000-71c78000 r--s 00000000 fe:00 3142                               /system/framework/boot-conscrypt.vdex
-Size:                404 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 404 kB
-Pss:                  47 kB
-Shared_Clean:        404 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          404 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               47 kB
-VmFlags: rd mr me ms 
-71c78000-71c79000 r--p 0003f000 fe:00 3205                               /system/framework/x86_64/boot-conscrypt.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-71c79000-71c7a000 rw-p 00040000 fe:00 3205                               /system/framework/x86_64/boot-conscrypt.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71c7a000-71c8e000 r--p 00000000 fe:00 3183                               /system/framework/x86_64/boot-okhttp.oat
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                  13 kB
-Shared_Clean:         80 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               13 kB
-VmFlags: rd mr mw me 
-71c8e000-71cd1000 r-xp 00014000 fe:00 3183                               /system/framework/x86_64/boot-okhttp.oat
-Size:                268 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 228 kB
-Pss:                 134 kB
-Shared_Clean:        188 kB
-Shared_Dirty:          0 kB
-Private_Clean:        40 kB
-Private_Dirty:         0 kB
-Referenced:          228 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              134 kB
-VmFlags: rd ex mr mw me 
-71cd1000-71cd2000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71cd2000-71d32000 r--s 00000000 fe:00 3135                               /system/framework/boot-okhttp.vdex
-Size:                384 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 312 kB
-Pss:                  71 kB
-Shared_Clean:        288 kB
-Shared_Dirty:          0 kB
-Private_Clean:        24 kB
-Private_Dirty:         0 kB
-Referenced:          312 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               71 kB
-VmFlags: rd mr me ms 
-71d32000-71d33000 r--p 00057000 fe:00 3183                               /system/framework/x86_64/boot-okhttp.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-71d33000-71d34000 rw-p 00058000 fe:00 3183                               /system/framework/x86_64/boot-okhttp.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71d34000-71d48000 r--p 00000000 fe:00 3200                               /system/framework/x86_64/boot-bouncycastle.oat
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-71d48000-71d84000 r-xp 00014000 fe:00 3200                               /system/framework/x86_64/boot-bouncycastle.oat
-Size:                240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 188 kB
-Pss:                  98 kB
-Shared_Clean:        180 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:          188 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               98 kB
-VmFlags: rd ex mr mw me 
-71d84000-71d85000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71d85000-71ec6000 r--s 00000000 fe:00 3145                               /system/framework/boot-bouncycastle.vdex
-Size:               1284 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 444 kB
-Pss:                  76 kB
-Shared_Clean:        444 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          444 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               76 kB
-VmFlags: rd mr me ms 
-71ec6000-71ec7000 r--p 00050000 fe:00 3200                               /system/framework/x86_64/boot-bouncycastle.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-71ec7000-71ec8000 rw-p 00051000 fe:00 3200                               /system/framework/x86_64/boot-bouncycastle.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71ec8000-71ed2000 r--p 00000000 fe:00 3187                               /system/framework/x86_64/boot-apache-xml.oat
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   2 kB
-Shared_Clean:         40 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-71ed2000-71eec000 r-xp 0000a000 fe:00 3187                               /system/framework/x86_64/boot-apache-xml.oat
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-71eec000-71eed000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-71eed000-72010000 r--s 00000000 fe:00 3212                               /system/framework/boot-apache-xml.vdex
-Size:               1164 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 320 kB
-Pss:                  35 kB
-Shared_Clean:        320 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          320 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               35 kB
-VmFlags: rd mr me ms 
-72010000-72011000 r--p 00024000 fe:00 3187                               /system/framework/x86_64/boot-apache-xml.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-72011000-72012000 rw-p 00025000 fe:00 3187                               /system/framework/x86_64/boot-apache-xml.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-72012000-7201d000 r--p 00000000 fe:00 3188                               /system/framework/x86_64/boot-ext.oat
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   2 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7201d000-72038000 r-xp 0000b000 fe:00 3188                               /system/framework/x86_64/boot-ext.oat
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 108 kB
-Pss:                  37 kB
-Shared_Clean:        108 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          108 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               37 kB
-VmFlags: rd ex mr mw me 
-72038000-72039000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-72039000-72124000 r--s 00000000 fe:00 3221                               /system/framework/boot-ext.vdex
-Size:                940 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 340 kB
-Pss:                  48 kB
-Shared_Clean:        340 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          340 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               48 kB
-VmFlags: rd mr me ms 
-72124000-72125000 r--p 00026000 fe:00 3188                               /system/framework/x86_64/boot-ext.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-72125000-72126000 rw-p 00027000 fe:00 3188                               /system/framework/x86_64/boot-ext.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-72126000-7240e000 r--p 00000000 fe:00 3189                               /system/framework/x86_64/boot-framework.oat
-Size:               2976 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2944 kB
-Pss:                 349 kB
-Shared_Clean:       2944 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2944 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              349 kB
-VmFlags: rd mr mw me 
-7240e000-72ee4000 r-xp 002e8000 fe:00 3189                               /system/framework/x86_64/boot-framework.oat
-Size:              11096 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               10444 kB
-Pss:                1678 kB
-Shared_Clean:      10252 kB
-Shared_Dirty:          0 kB
-Private_Clean:       192 kB
-Private_Dirty:         0 kB
-Referenced:        10444 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1678 kB
-VmFlags: rd ex mr mw me 
-72ee4000-72ee6000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-72ee6000-7449a000 r--s 00000000 fe:00 3156                               /system/framework/boot-framework.vdex
-Size:              22224 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               16932 kB
-Pss:                2196 kB
-Shared_Clean:      16872 kB
-Shared_Dirty:          0 kB
-Private_Clean:        60 kB
-Private_Dirty:         0 kB
-Referenced:        16932 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2196 kB
-VmFlags: rd mr me ms 
-7449a000-7449b000 r--p 00dbe000 fe:00 3189                               /system/framework/x86_64/boot-framework.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7449b000-7449c000 rw-p 00dbf000 fe:00 3189                               /system/framework/x86_64/boot-framework.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7449c000-744f8000 r--p 00000000 fe:00 3202                               /system/framework/x86_64/boot-telephony-common.oat
-Size:                368 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                   5 kB
-Shared_Clean:         80 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-744f8000-7463c000 r-xp 0005c000 fe:00 3202                               /system/framework/x86_64/boot-telephony-common.oat
-Size:               1296 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7463c000-7463d000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7463d000-74974000 r--s 00000000 fe:00 3209                               /system/framework/boot-telephony-common.vdex
-Size:               3292 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 344 kB
-Pss:                  21 kB
-Shared_Clean:        344 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          344 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr me ms 
-74974000-74975000 r--p 001a0000 fe:00 3202                               /system/framework/x86_64/boot-telephony-common.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-74975000-74976000 rw-p 001a1000 fe:00 3202                               /system/framework/x86_64/boot-telephony-common.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-74976000-74978000 r--p 00000000 fe:00 3193                               /system/framework/x86_64/boot-voip-common.oat
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-74978000-7497a000 r-xp 00002000 fe:00 3193                               /system/framework/x86_64/boot-voip-common.oat
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7497a000-7497b000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7497b000-749a1000 r--s 00000000 fe:00 3397                               /system/framework/boot-voip-common.vdex
-Size:                152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 144 kB
-Pss:                  14 kB
-Shared_Clean:        144 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          144 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd mr me ms 
-749a1000-749a2000 r--p 00004000 fe:00 3193                               /system/framework/x86_64/boot-voip-common.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-749a2000-749a3000 rw-p 00005000 fe:00 3193                               /system/framework/x86_64/boot-voip-common.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-749a3000-749a9000 r--p 00000000 fe:00 3191                               /system/framework/x86_64/boot-ims-common.oat
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-749a9000-749b7000 r-xp 00006000 fe:00 3191                               /system/framework/x86_64/boot-ims-common.oat
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-749b7000-749b8000 rw-p 00000000 00:00 0                                  [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-749b8000-749db000 r--s 00000000 fe:00 3152                               /system/framework/boot-ims-common.vdex
-Size:                140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 104 kB
-Pss:                   6 kB
-Shared_Clean:        104 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          104 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr me ms 
-749db000-749dc000 r--p 00014000 fe:00 3191                               /system/framework/x86_64/boot-ims-common.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-749dc000-749dd000 rw-p 00015000 fe:00 3191                               /system/framework/x86_64/boot-ims-common.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-749dd000-749df000 r--p 00000000 fe:00 3194                               /system/framework/x86_64/boot-framework-oahl-backward-compatibility.oat
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-749df000-749e0000 r-xp 00002000 fe:00 3194                               /system/framework/x86_64/boot-framework-oahl-backward-compatibility.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-749e0000-749e1000 r--s 00000000 fe:00 3147                               /system/framework/boot-framework-oahl-backward-compatibility.vdex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-749e1000-749e2000 r--p 00003000 fe:00 3194                               /system/framework/x86_64/boot-framework-oahl-backward-compatibility.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-749e2000-749e3000 rw-p 00004000 fe:00 3194                               /system/framework/x86_64/boot-framework-oahl-backward-compatibility.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-749e3000-749e5000 r--p 00000000 fe:00 3180                               /system/framework/x86_64/boot-android.test.base.impl.oat
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-749e5000-749e6000 r-xp 00002000 fe:00 3180                               /system/framework/x86_64/boot-android.test.base.impl.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-749e6000-749ee000 r--s 00000000 fe:00 3350                               /system/framework/boot-android.test.base.impl.vdex
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-749ee000-749ef000 r--p 00003000 fe:00 3180                               /system/framework/x86_64/boot-android.test.base.impl.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-749ef000-749f0000 rw-p 00004000 fe:00 3180                               /system/framework/x86_64/boot-android.test.base.impl.oat
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-749f0000-74b3d000 rw-p 00000000 00:00 0                                  [anon:dalvik-zygote space]
-Name:           [anon:dalvik-zygote space]
-Size:               1332 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1332 kB
-Pss:                 497 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        884 kB
-Private_Clean:         0 kB
-Private_Dirty:       448 kB
-Referenced:          564 kB
-Anonymous:          1332 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              497 kB
-VmFlags: rd wr mr mw me ac 
-74b3d000-74b3e000 rw-p 00000000 00:00 0                                  [anon:dalvik-non moving space]
-Name:           [anon:dalvik-non moving space]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-74b3e000-74b71000 rw-p 00000000 00:00 0                                  [anon:dalvik-non moving space]
-Name:           [anon:dalvik-non moving space]
-Size:                204 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 204 kB
-Pss:                 204 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       204 kB
-Referenced:          204 kB
-Anonymous:           204 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              204 kB
-VmFlags: rd wr mr mw me ac 
-74b71000-781f1000 ---p 00000000 00:00 0                                  [anon:dalvik-non moving space]
-Name:           [anon:dalvik-non moving space]
-Size:              55808 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-781f1000-789f0000 rw-p 00000000 00:00 0                                  [anon:dalvik-non moving space]
-Name:           [anon:dalvik-non moving space]
-Size:               8188 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-ebad6000-ebad7000 ---p 00000000 00:00 0                                  [anon:dalvik-Sentinel fault page]
-Name:           [anon:dalvik-Sentinel fault page]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-578de5770000-578de5773000 r--p 00000000 fe:00 408                        /system/bin/app_process64
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   1 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me dw 
-578de5773000-578de5777000 r-xp 00003000 fe:00 408                        /system/bin/app_process64
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me dw 
-578de5777000-578de5778000 r--p 00007000 fe:00 408                        /system/bin/app_process64
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me dw ac 
-578de5778000-578de577a000 rw-p 00000000 00:00 0 
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700749747000-7007497f6000 rw-s 00000000 00:05 12329                      /dev/ashmem/gralloc-1332.3 (deleted)
-Size:                700 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 656 kB
-Pss:                 656 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       656 kB
-Referenced:          656 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              656 kB
-VmFlags: rd wr sh mr mw me ms 
-7007497f6000-7007497f7000 ---s 000af000 00:05 12329                      /dev/ashmem/gralloc-1332.3 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: sh mr mw me ms 
-7007497f7000-7007498a6000 rw-s 00000000 00:05 12330                      /dev/ashmem/gralloc-1332.4 (deleted)
-Size:                700 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 656 kB
-Pss:                 656 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       656 kB
-Referenced:          656 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              656 kB
-VmFlags: rd wr sh mr mw me ms 
-7007498a6000-7007498a7000 ---s 000af000 00:05 12330                      /dev/ashmem/gralloc-1332.4 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: sh mr mw me ms 
-7007498a7000-700749956000 rw-s 00000000 00:05 12331                      /dev/ashmem/gralloc-1332.5 (deleted)
-Size:                700 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 656 kB
-Pss:                 328 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        656 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          656 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              328 kB
-VmFlags: rd wr sh mr mw me ms 
-700749956000-700749957000 ---s 000af000 00:05 12331                      /dev/ashmem/gralloc-1332.5 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: sh mr mw me ms 
-700749957000-70074995b000 r--p 00000000 fe:30 346                        /vendor/lib64/hw/gralloc.vsoc.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   2 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-70074995b000-70074995e000 r-xp 00004000 fe:30 346                        /vendor/lib64/hw/gralloc.vsoc.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   1 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-70074995e000-70074995f000 rw-p 00007000 fe:30 346                        /vendor/lib64/hw/gralloc.vsoc.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70074995f000-700749960000 r--p 00008000 fe:30 346                        /vendor/lib64/hw/gralloc.vsoc.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700749960000-700749961000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700749981000-70074998a000 r--p 00000000 fe:30 381                        /vendor/lib64/vsoc_lib.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   3 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-70074998a000-700749992000 r-xp 00009000 fe:30 381                        /vendor/lib64/vsoc_lib.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700749992000-700749993000 rw-p 00011000 fe:30 381                        /vendor/lib64/vsoc_lib.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700749993000-700749994000 r--p 00012000 fe:30 381                        /vendor/lib64/vsoc_lib.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700749994000-700749995000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007499f7000-70074a5f7000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:              12288 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70074a909000-70074a90a000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074a90a000-70074a90b000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074a90b000-70074aa0f000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70074aa0f000-70074ab0f000 rw-s 00000000 00:05 11658                      /dev/ashmem/MemoryHeapBase (deleted)
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr sh mr mw me ms 
-70074ab0f000-70074ac0f000 rw-s 00000000 00:05 11656                      /dev/ashmem/MemoryHeapBase (deleted)
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr sh mr mw me ms 
-70074ac0f000-70074c78d000 r--s 00bc3000 fe:00 3346                       /system/framework/framework-res.apk
-Size:              28152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               19268 kB
-Pss:                 933 kB
-Shared_Clean:      19268 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:        19268 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              933 kB
-VmFlags: rd mr me ms 
-70074c78d000-70074c78e000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074c78e000-70074c78f000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074c78f000-70074c893000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70074c893000-70074d293000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:              10240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 536 kB
-Pss:                 536 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       536 kB
-Referenced:          208 kB
-Anonymous:           536 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              536 kB
-VmFlags: rd wr mr mw me ac 
-70074d293000-70074d294000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074d294000-70074d295000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074d295000-70074d399000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70074d399000-70074db99000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               8192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70074db99000-70074db9a000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074db9a000-70074dc93000 rw-p 00000000 00:00 0 
-Size:                996 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me nr 
-70074dc93000-70074dc94000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074dc94000-70074dd8d000 rw-p 00000000 00:00 0 
-Size:                996 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70074dd8d000-70074ee0d000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:              16896 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               15272 kB
-Pss:               15272 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:     15272 kB
-Referenced:        11156 kB
-Anonymous:         15272 kB
-AnonHugePages:      6144 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:            15272 kB
-VmFlags: rd wr mr mw me ac 
-70074ee0d000-70074ee0e000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074ee0e000-70074ee0f000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074ee0f000-70074ef13000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70074ef13000-70074f493000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               5632 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                5348 kB
-Pss:                5348 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      5348 kB
-Referenced:         3364 kB
-Anonymous:          5348 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             5348 kB
-VmFlags: rd wr mr mw me ac 
-70074f493000-70074f8a0000 r--s 001a6000 fe:00 1821                       /system/priv-app/Telecom/Telecom.apk
-Size:               4148 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr me ms 
-70074f8e1000-70074f9e1000 rw-s 00000000 00:05 11617                      /dev/ashmem/MemoryHeapBase (deleted)
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr sh mr mw me ms 
-70074f9e1000-70074fae1000 rw-s 00000000 00:05 11565                      /dev/ashmem/MemoryHeapBase (deleted)
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr sh mr mw me ms 
-70074fae1000-70074fae2000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074fae2000-70074fae3000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074fae3000-70074fbe7000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70074fbe7000-70074fca2000 r--s 0287a000 fe:00 3346                       /system/framework/framework-res.apk
-Size:                748 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 748 kB
-Pss:                 160 kB
-Shared_Clean:        748 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          748 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              160 kB
-VmFlags: rd mr me ms 
-70074fca2000-70074fca4000 r--p 00000000 fe:00 2040                       /system/priv-app/FusedLocation/oat/x86_64/FusedLocation.odex
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-70074fca4000-70074fca7000 r-xp 00002000 fe:00 2040                       /system/priv-app/FusedLocation/oat/x86_64/FusedLocation.odex
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me 
-70074fca7000-70074fca8000 r--p 00005000 fe:00 2040                       /system/priv-app/FusedLocation/oat/x86_64/FusedLocation.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-70074fca8000-70074fca9000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70074fca9000-70074fcaa000 r--s 00000000 fe:00 2039                       /system/priv-app/FusedLocation/oat/x86_64/FusedLocation.vdex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr me ms 
-70074fcaa000-70074fcab000 r--p 00006000 fe:00 2040                       /system/priv-app/FusedLocation/oat/x86_64/FusedLocation.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-70074fcab000-70074fcac000 rw-p 00007000 fe:00 2040                       /system/priv-app/FusedLocation/oat/x86_64/FusedLocation.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70074fcef000-70074fcf2000 r--p 00000000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-70074fcf2000-70074fcf6000 r-xp 00003000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd ex mr mw me 
-70074fcf6000-70074fcf7000 r--p 00007000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-70074fcf7000-70074fcf8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70074fcf8000-70074fcfd000 r--s 00000000 fe:00 3249                       /system/framework/oat/x86_64/com.android.location.provider.impl.vdex
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  10 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr me ms 
-70074fcfd000-70074fcfe000 r--p 00008000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-70074fcfe000-70074fcff000 rw-p 00009000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70074fd15000-70074fe15000 rw-s 00000000 00:05 11532                      /dev/ashmem/MemoryHeapBase (deleted)
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr sh mr mw me ms 
-70074fe15000-70074fe16000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074fe16000-70074fe17000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70074fe17000-70074ff1b000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70074ff1b000-70074ffa5000 r--p 00000000 fe:00 1819                       /system/priv-app/Telecom/oat/x86_64/Telecom.odex
-Size:                552 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                  72 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        72 kB
-Private_Dirty:         0 kB
-Referenced:           72 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               72 kB
-VmFlags: rd mr mw me 
-70074ffa5000-7007501f2000 r-xp 0008a000 fe:00 1819                       /system/priv-app/Telecom/oat/x86_64/Telecom.odex
-Size:               2356 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1784 kB
-Pss:                1784 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:      1784 kB
-Private_Dirty:         0 kB
-Referenced:         1784 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1784 kB
-VmFlags: rd ex mr mw me 
-7007501f2000-7007501f4000 r--p 002d7000 fe:00 1819                       /system/priv-app/Telecom/oat/x86_64/Telecom.odex
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007501f4000-7007501f9000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me ac 
-7007501f9000-7007501fe000 r--s 00000000 fe:00 1820                       /system/priv-app/Telecom/oat/x86_64/Telecom.vdex
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        20 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr me ms 
-7007501fe000-7007501ff000 r--p 002d9000 fe:00 1819                       /system/priv-app/Telecom/oat/x86_64/Telecom.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007501ff000-700750200000 rw-p 002da000 fe:00 1819                       /system/priv-app/Telecom/oat/x86_64/Telecom.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700750296000-700750297000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700750297000-700750298000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700750298000-70075039c000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075039c000-70075039d000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075039d000-70075039e000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075039e000-700750496000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700750496000-70075056f000 r--s 003f5000 fe:00 1805                       /system/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk
-Size:                868 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 384 kB
-Pss:                 192 kB
-Shared_Clean:        384 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          384 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              192 kB
-VmFlags: rd mr me ms 
-7007509c2000-700750dc2000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               4096 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1980 kB
-Pss:                1980 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      1980 kB
-Referenced:          176 kB
-Anonymous:          1980 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1980 kB
-VmFlags: rd wr mr mw me ac 
-70075185d000-70075185e000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075185e000-70075185f000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075185f000-700751957000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700751adb000-700751adc000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751adc000-700751add000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751add000-700751be1000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        28 kB
-Referenced:           28 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd wr mr mw me nr 
-700751d30000-700751d31000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751d31000-700751d32000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751d32000-700751e2a000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700751e50000-700751e51000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751e51000-700751e52000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751e52000-700751f56000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700751f56000-700751f57000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751f57000-700751f58000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700751f58000-70075205c000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075205c000-70075205d000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075205d000-70075205e000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075205e000-700752162000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700752162000-700752163000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752163000-700752164000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752164000-70075225c000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075225c000-70075225d000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075225d000-70075225e000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075225e000-700752362000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700752362000-700752363000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752363000-700752364000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752364000-700752468000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700752474000-700752475000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752475000-700752476000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752476000-70075256e000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075256e000-70075266e000 rw-s 00000000 00:05 11287                      /dev/ashmem/MemoryHeapBase (deleted)
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr sh mr mw me ms 
-70075266e000-70075266f000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075266f000-700752670000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752670000-700752774000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700752780000-700752781000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752781000-700752782000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752782000-70075287a000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70075287a000-70075287b000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075287b000-70075287c000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075287c000-700752980000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700752980000-700752981000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752981000-700752982000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752982000-700752a7a000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700752a7a000-700752a7b000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752a7b000-700752a7c000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752a7c000-700752b74000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700752b74000-700752b75000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752b75000-700752b76000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752b76000-700752c6e000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700752cb5000-700752cb8000 r--p 00000000 fe:00 1482                       /system/lib64/vndk-sp-Q/hw/android.hidl.memory@1.0-impl.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-700752cb8000-700752cb9000 r-xp 00003000 fe:00 1482                       /system/lib64/vndk-sp-Q/hw/android.hidl.memory@1.0-impl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-700752cb9000-700752cba000 rw-p 00004000 fe:00 1482                       /system/lib64/vndk-sp-Q/hw/android.hidl.memory@1.0-impl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700752cba000-700752cbb000 r--p 00005000 fe:00 1482                       /system/lib64/vndk-sp-Q/hw/android.hidl.memory@1.0-impl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700752cbb000-700752cbc000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700752cf5000-700752cf6000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752cf6000-700752cf7000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752cf7000-700752dfb000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700752dfb000-700752dfc000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752dfc000-700752dfd000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752dfd000-700752ef5000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700752ef5000-700752ef6000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752ef6000-700752ef7000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752ef7000-700752fef000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700752fef000-700752ff0000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752ff0000-700752ff1000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700752ff1000-7007530e9000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700753145000-700753148000 r--p 00000000 fe:30 382                        /vendor/lib64/libcuttlefish_fs.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   1 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700753148000-70075314d000 r-xp 00003000 fe:30 382                        /vendor/lib64/libcuttlefish_fs.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-70075314d000-70075314e000 rw-p 00008000 fe:30 382                        /vendor/lib64/libcuttlefish_fs.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075314e000-70075314f000 r--p 00009000 fe:30 382                        /vendor/lib64/libcuttlefish_fs.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-70075319d000-70075319e000 r--p 00000000 fe:30 408                        /vendor/lib64/cuttlefish_auto_resources.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-70075319e000-70075319f000 r-xp 00001000 fe:30 408                        /vendor/lib64/cuttlefish_auto_resources.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-70075319f000-7007531a0000 rw-p 00002000 fe:30 408                        /vendor/lib64/cuttlefish_auto_resources.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007531a0000-7007531a1000 r--p 00003000 fe:30 408                        /vendor/lib64/cuttlefish_auto_resources.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007531e3000-7007531e4000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007531e4000-7007531e5000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007531e5000-7007532e9000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-7007532e9000-700753669000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               3584 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                3060 kB
-Pss:                3060 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      3060 kB
-Referenced:         1816 kB
-Anonymous:          3060 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             3060 kB
-VmFlags: rd wr mr mw me ac 
-700753669000-70075366a000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075366a000-70075366b000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075366b000-70075376f000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075376f000-700753770000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753770000-700753771000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753771000-700753875000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700753875000-700753876000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753876000-700753877000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753877000-70075397b000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70075397b000-70075397c000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075397c000-70075397d000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075397d000-700753a81000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700753a81000-700753a82000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753a82000-700753a83000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753a83000-700753b87000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700753b87000-700753b88000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753b88000-700753b89000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753b89000-700753c8d000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700753c8d000-700753c8e000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753c8e000-700753c8f000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753c8f000-700753d93000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700753d93000-700753d94000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753d94000-700753d95000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753d95000-700753e99000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700753e99000-700753e9a000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753e9a000-700753e9b000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753e9b000-700753f9f000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        28 kB
-Referenced:           28 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd wr mr mw me nr 
-700753f9f000-700753fa0000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753fa0000-700753fa1000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700753fa1000-700754099000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700754099000-70075409a000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075409a000-70075409b000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075409b000-70075419f000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075419f000-7007541a0000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007541a0000-7007541a1000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007541a1000-7007542a5000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007542a5000-7007542a6000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007542a6000-7007542a7000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007542a7000-7007543ab000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007543ab000-7007543ac000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007543ac000-7007543ad000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007543ad000-7007544b1000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007544b1000-7007544b2000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007544b2000-7007544b3000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007544b3000-7007545b7000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007545b7000-7007545b8000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007545b8000-7007545b9000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007545b9000-7007546bd000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007546bd000-7007546be000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007546be000-7007546bf000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007546bf000-7007547c3000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-7007547c3000-7007547c4000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007547c4000-7007547c5000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007547c5000-7007548c9000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007548c9000-7007548ca000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007548ca000-7007548cb000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007548cb000-7007549cf000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007549cf000-7007549d0000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007549d0000-7007549d1000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007549d1000-700754ad5000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700754ad5000-700754ad6000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754ad6000-700754ad7000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754ad7000-700754bdb000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700754bdb000-700754bdc000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754bdc000-700754bdd000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754bdd000-700754ce1000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700754ce1000-700754ce2000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754ce2000-700754ce3000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754ce3000-700754de7000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700754de7000-700754de8000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754de8000-700754de9000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754de9000-700754eed000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700754eed000-700754eee000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754eee000-700754eef000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754eef000-700754ff3000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700754ff3000-700754ff4000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754ff4000-700754ff5000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700754ff5000-7007550f9000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007550f9000-7007550fa000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007550fa000-7007550fb000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007550fb000-7007551ff000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007551ff000-700755200000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755200000-700755201000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755201000-700755305000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700755305000-700755306000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755306000-700755307000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755307000-70075540b000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075540b000-70075540c000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075540c000-70075540d000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075540d000-700755511000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700755511000-700755512000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755512000-700755513000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755513000-70075560b000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me nr 
-70075560b000-70075560c000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075560c000-70075560d000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075560d000-700755705000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700755705000-700755706000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755706000-700755707000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755707000-70075580b000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70075580b000-70075580c000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075580c000-70075580d000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075580d000-700755911000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700755911000-700755912000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755912000-700755913000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755913000-700755a17000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700755a17000-700755a2d000 r--p 00000000 fe:00 1947                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex
-Size:                 88 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  88 kB
-Pss:                  88 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        88 kB
-Private_Dirty:         0 kB
-Referenced:           88 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               88 kB
-VmFlags: rd mr mw me 
-700755a2d000-700755a6e000 r-xp 00016000 fe:00 1947                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex
-Size:                260 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 260 kB
-Pss:                 260 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       260 kB
-Private_Dirty:         0 kB
-Referenced:          260 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              260 kB
-VmFlags: rd ex mr mw me 
-700755a6e000-700755a6f000 r--p 00057000 fe:00 1947                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700755a6f000-700755a70000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700755a70000-700755a71000 r--s 00000000 fe:00 1946                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.vdex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr me ms 
-700755a71000-700755a72000 r--p 00058000 fe:00 1947                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-700755a72000-700755a73000 rw-p 00059000 fe:00 1947                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700755aae000-700755aaf000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755aaf000-700755ab0000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755ab0000-700755bb4000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700755bb4000-700755bb5000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755bb5000-700755bb6000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755bb6000-700755cba000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700755cba000-700755cbb000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755cbb000-700755cbc000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755cbc000-700755db4000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700755db4000-700755db5000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755db5000-700755db6000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700755db6000-700755eae000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700755f18000-700755f28000 r--p 00000000 fe:00 1483                       /system/lib64/vndk-sp-Q/android.hidl.memory@1.0.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  32 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr mw me 
-700755f28000-700755f3c000 r-xp 00010000 fe:00 1483                       /system/lib64/vndk-sp-Q/android.hidl.memory@1.0.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                  40 kB
-Shared_Clean:         80 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               40 kB
-VmFlags: rd ex mr mw me 
-700755f3c000-700755f3d000 rw-p 00024000 fe:00 1483                       /system/lib64/vndk-sp-Q/android.hidl.memory@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700755f3d000-700755f40000 r--p 00025000 fe:00 1483                       /system/lib64/vndk-sp-Q/android.hidl.memory@1.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-700755f71000-7007560ba000 r--p 00000000 fe:00 1821                       /system/priv-app/Telecom/Telecom.apk
-Size:               1316 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       128 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd mr mw me ac 
-7007560ba000-7007560bb000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007560bb000-7007560bc000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007560bc000-7007561c0000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007561c0000-7007561c1000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007561c1000-7007561c2000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007561c2000-7007562c6000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007562c6000-7007562c7000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007562c7000-7007562c8000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007562c8000-7007563cc000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007563d8000-7007563d9000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007563d9000-7007563da000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007563da000-7007564d2000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                  72 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        72 kB
-Referenced:           72 kB
-Anonymous:            72 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               72 kB
-VmFlags: rd wr mr mw me nr 
-7007564d2000-7007564d3000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007564d3000-7007564d4000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007564d4000-7007565d8000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007565d8000-7007565d9000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007565d9000-7007565da000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007565da000-7007566de000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007566de000-7007566df000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007566df000-7007566e0000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007566e0000-7007567e4000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-7007567e4000-7007567e5000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007567e5000-7007567e6000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007567e6000-7007568de000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007568de000-7007568df000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007568df000-7007568e0000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007568e0000-7007569e4000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007569e4000-7007569e5000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007569e5000-7007569e6000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007569e6000-700756aea000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700756aea000-700756aeb000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756aeb000-700756aec000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756aec000-700756bf0000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  76 kB
-Pss:                  76 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        76 kB
-Referenced:           76 kB
-Anonymous:            76 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               76 kB
-VmFlags: rd wr mr mw me nr 
-700756bf0000-700756bf1000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756bf1000-700756bf2000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756bf2000-700756cf6000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700756cf6000-700756cf7000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756cf7000-700756cf8000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756cf8000-700756dfc000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700756dfc000-700756dfd000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756dfd000-700756dfe000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700756dfe000-700756f02000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700756f02000-700757000000 r--p 00000000 00:13 6792                       /dev/hwbinder
-Size:               1016 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr me dc nr mm 
-700757000000-700757400000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               4096 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2048 kB
-Pss:                2048 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      2048 kB
-Referenced:         2048 kB
-Anonymous:          2048 kB
-AnonHugePages:      2048 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2048 kB
-VmFlags: rd wr mr mw me ac 
-700757442000-700757443000 r--p 00000000 fe:00 1554                       /system/lib64/libwifi-service.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-700757443000-700757444000 r-xp 00001000 fe:00 1554                       /system/lib64/libwifi-service.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me 
-700757444000-700757445000 rw-p 00002000 fe:00 1554                       /system/lib64/libwifi-service.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700757445000-700757446000 r--p 00003000 fe:00 1554                       /system/lib64/libwifi-service.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-70075749f000-7007574a0000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007574a0000-7007574a1000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007574a1000-7007575a5000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007575a5000-7007578a5000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               3072 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2728 kB
-Pss:                2728 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:      2728 kB
-Referenced:         1524 kB
-Anonymous:          2728 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2728 kB
-VmFlags: rd wr mr mw me ac 
-7007578a5000-7007578a6000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007578a6000-7007578a7000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007578a7000-7007579ab000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-7007579ab000-7007579ac000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007579ac000-7007579ad000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-7007579ad000-700757ab1000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-700757ab1000-700757ab2000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757ab2000-700757ab3000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757ab3000-700757bb7000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me nr 
-700757bb7000-700757bb8000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757bb8000-700757bb9000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757bb9000-700757cbd000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  24 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        24 kB
-Referenced:           24 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd wr mr mw me nr 
-700757cbd000-700757cbe000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757cbe000-700757cbf000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757cbf000-700757dc3000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        28 kB
-Referenced:           28 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd wr mr mw me nr 
-700757dcf000-700757dd0000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757dd0000-700757dd1000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700757dd1000-700757ec9000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-700757ec9000-700757ed4000 r--p 00000000 fe:00 1737                       /system/lib64/android.hardware.vibrator@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700757ed4000-700757ee0000 r-xp 0000b000 fe:00 1737                       /system/lib64/android.hardware.vibrator@1.0.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  48 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        48 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               48 kB
-VmFlags: rd ex mr mw me 
-700757ee0000-700757ee1000 rw-p 00017000 fe:00 1737                       /system/lib64/android.hardware.vibrator@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700757ee1000-700757ee3000 r--p 00018000 fe:00 1737                       /system/lib64/android.hardware.vibrator@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700757f0c000-700757f3c000 r--p 00000000 fe:00 1129                       /system/lib64/libinputflinger.so
-Size:                192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 112 kB
-Pss:                 112 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       112 kB
-Private_Dirty:         0 kB
-Referenced:          112 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              112 kB
-VmFlags: rd mr mw me 
-700757f3c000-700757f6f000 r-xp 00030000 fe:00 1129                       /system/lib64/libinputflinger.so
-Size:                204 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 200 kB
-Pss:                 200 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       200 kB
-Private_Dirty:         0 kB
-Referenced:          200 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              200 kB
-VmFlags: rd ex mr mw me 
-700757f6f000-700757f70000 rw-p 00063000 fe:00 1129                       /system/lib64/libinputflinger.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700757f70000-700757f74000 r--p 00064000 fe:00 1129                       /system/lib64/libinputflinger.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me ac 
-700757f74000-700757f75000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700757f82000-700757faa000 r--p 00000000 fe:00 1625                       /system/lib64/android.hardware.gnss@1.1.so
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                  68 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        68 kB
-Private_Dirty:         0 kB
-Referenced:           68 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               68 kB
-VmFlags: rd mr mw me 
-700757faa000-700757fe1000 r-xp 00028000 fe:00 1625                       /system/lib64/android.hardware.gnss@1.1.so
-Size:                220 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 216 kB
-Pss:                 216 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       216 kB
-Private_Dirty:         0 kB
-Referenced:          216 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              216 kB
-VmFlags: rd ex mr mw me 
-700757fe1000-700757fe2000 rw-p 0005f000 fe:00 1625                       /system/lib64/android.hardware.gnss@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700757fe2000-700757fea000 r--p 00060000 fe:00 1625                       /system/lib64/android.hardware.gnss@1.1.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        32 kB
-Referenced:           32 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr mw me ac 
-700758023000-70075802d000 r--p 00000000 fe:00 1510                       /system/lib64/android.hardware.tetheroffload.config@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        20 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me 
-70075802d000-700758036000 r-xp 0000a000 fe:00 1510                       /system/lib64/android.hardware.tetheroffload.config@1.0.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                  36 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        36 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               36 kB
-VmFlags: rd ex mr mw me 
-700758036000-700758037000 rw-p 00013000 fe:00 1510                       /system/lib64/android.hardware.tetheroffload.config@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758037000-700758039000 r--p 00014000 fe:00 1510                       /system/lib64/android.hardware.tetheroffload.config@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758043000-700758053000 r--p 00000000 fe:00 1259                       /system/lib64/libkeymaster4support.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700758053000-700758069000 r-xp 00010000 fe:00 1259                       /system/lib64/libkeymaster4support.so
-Size:                 88 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700758069000-70075806a000 rw-p 00026000 fe:00 1259                       /system/lib64/libkeymaster4support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075806a000-70075806c000 r--p 00027000 fe:00 1259                       /system/lib64/libkeymaster4support.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758089000-700758099000 r--p 00000000 fe:00 1175                       /system/lib64/android.hardware.tv.input@1.0.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-700758099000-7007580ab000 r-xp 00010000 fe:00 1175                       /system/lib64/android.hardware.tv.input@1.0.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                  72 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        72 kB
-Private_Dirty:         0 kB
-Referenced:           72 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               72 kB
-VmFlags: rd ex mr mw me 
-7007580ab000-7007580ac000 rw-p 00022000 fe:00 1175                       /system/lib64/android.hardware.tv.input@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007580ac000-7007580af000 r--p 00023000 fe:00 1175                       /system/lib64/android.hardware.tv.input@1.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-7007580d7000-7007580d8000 r--p 00000000 fe:00 1648                       /system/lib64/android.hardware.audio.common@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007580d8000-7007580d9000 r-xp 00001000 fe:00 1648                       /system/lib64/android.hardware.audio.common@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007580d9000-7007580da000 rw-p 00002000 fe:00 1648                       /system/lib64/android.hardware.audio.common@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007580da000-7007580db000 r--p 00003000 fe:00 1648                       /system/lib64/android.hardware.audio.common@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700758110000-700758122000 r--p 00000000 fe:00 1680                       /system/lib64/android.hardware.tv.cec@1.0.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-700758122000-70075813c000 r-xp 00012000 fe:00 1680                       /system/lib64/android.hardware.tv.cec@1.0.so
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 104 kB
-Pss:                 104 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       104 kB
-Private_Dirty:         0 kB
-Referenced:          104 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              104 kB
-VmFlags: rd ex mr mw me 
-70075813c000-70075813d000 rw-p 0002c000 fe:00 1680                       /system/lib64/android.hardware.tv.cec@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075813d000-700758140000 r--p 0002d000 fe:00 1680                       /system/lib64/android.hardware.tv.cec@1.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-700758153000-70075815e000 r--p 00000000 fe:00 1725                       /system/lib64/android.hardware.thermal@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  14 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd mr mw me 
-70075815e000-700758169000 r-xp 0000b000 fe:00 1725                       /system/lib64/android.hardware.thermal@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  14 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd ex mr mw me 
-700758169000-70075816a000 rw-p 00016000 fe:00 1725                       /system/lib64/android.hardware.thermal@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075816a000-70075816c000 r--p 00017000 fe:00 1725                       /system/lib64/android.hardware.thermal@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758198000-7007581a3000 r--p 00000000 fe:00 1171                       /system/lib64/android.hardware.power@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  14 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd mr mw me 
-7007581a3000-7007581ae000 r-xp 0000b000 fe:00 1171                       /system/lib64/android.hardware.power@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  14 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd ex mr mw me 
-7007581ae000-7007581af000 rw-p 00016000 fe:00 1171                       /system/lib64/android.hardware.power@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007581af000-7007581b1000 r--p 00017000 fe:00 1171                       /system/lib64/android.hardware.power@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007581c1000-7007581e1000 r--s 00000000 00:13 6677                       /dev/__properties__/u:object_r:boottime_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr me ms 
-7007581e1000-7007581ec000 r--p 00000000 fe:00 1568                       /system/lib64/android.hardware.vibrator@1.1.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-7007581ec000-7007581f7000 r-xp 0000b000 fe:00 1568                       /system/lib64/android.hardware.vibrator@1.1.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  44 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        44 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               44 kB
-VmFlags: rd ex mr mw me 
-7007581f7000-7007581f8000 rw-p 00016000 fe:00 1568                       /system/lib64/android.hardware.vibrator@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007581f8000-7007581fa000 r--p 00017000 fe:00 1568                       /system/lib64/android.hardware.vibrator@1.1.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758202000-700758212000 r--p 00000000 fe:00 1534                       /system/lib64/android.hardware.keymaster@3.0.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700758212000-70075822d000 r-xp 00010000 fe:00 1534                       /system/lib64/android.hardware.keymaster@3.0.so
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 108 kB
-Pss:                  27 kB
-Shared_Clean:        108 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          108 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               27 kB
-VmFlags: rd ex mr mw me 
-70075822d000-70075822e000 rw-p 0002b000 fe:00 1534                       /system/lib64/android.hardware.keymaster@3.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075822e000-700758231000 r--p 0002c000 fe:00 1534                       /system/lib64/android.hardware.keymaster@3.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-700758243000-70075824d000 r--p 00000000 fe:00 1257                       /system/lib64/android.hardware.vr@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        20 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me 
-70075824d000-700758256000 r-xp 0000a000 fe:00 1257                       /system/lib64/android.hardware.vr@1.0.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                  36 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        36 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               36 kB
-VmFlags: rd ex mr mw me 
-700758256000-700758257000 rw-p 00013000 fe:00 1257                       /system/lib64/android.hardware.vr@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758257000-700758259000 r--p 00014000 fe:00 1257                       /system/lib64/android.hardware.vr@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758267000-700758287000 r--s 00000000 00:13 6710                       /dev/__properties__/u:object_r:firstboot_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700758287000-700758299000 r--p 00000000 fe:00 1586                       /system/lib64/android.hardware.keymaster@4.0.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700758299000-7007582ba000 r-xp 00012000 fe:00 1586                       /system/lib64/android.hardware.keymaster@4.0.so
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 104 kB
-Pss:                  26 kB
-Shared_Clean:        104 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          104 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               26 kB
-VmFlags: rd ex mr mw me 
-7007582ba000-7007582bb000 rw-p 00033000 fe:00 1586                       /system/lib64/android.hardware.keymaster@4.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007582bb000-7007582be000 r--p 00034000 fe:00 1586                       /system/lib64/android.hardware.keymaster@4.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-7007582ce000-7007582ea000 r--p 00000000 fe:00 1729                       /system/lib64/android.frameworks.sensorservice@1.0.so
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-7007582ea000-70075830d000 r-xp 0001c000 fe:00 1729                       /system/lib64/android.frameworks.sensorservice@1.0.so
-Size:                140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 140 kB
-Pss:                 140 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       140 kB
-Private_Dirty:         0 kB
-Referenced:          140 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              140 kB
-VmFlags: rd ex mr mw me 
-70075830d000-70075830e000 rw-p 0003f000 fe:00 1729                       /system/lib64/android.frameworks.sensorservice@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075830e000-700758313000 r--p 00040000 fe:00 1729                       /system/lib64/android.frameworks.sensorservice@1.0.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me ac 
-700758367000-7007583d9000 r--p 00000000 fe:00 1138                       /system/lib64/android.hardware.gnss@1.0.so
-Size:                456 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  64 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        64 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               64 kB
-VmFlags: rd mr mw me 
-7007583d9000-700758494000 r-xp 00072000 fe:00 1138                       /system/lib64/android.hardware.gnss@1.0.so
-Size:                748 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 724 kB
-Pss:                 724 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       724 kB
-Private_Dirty:         0 kB
-Referenced:          724 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              724 kB
-VmFlags: rd ex mr mw me 
-700758494000-700758495000 rw-p 0012d000 fe:00 1138                       /system/lib64/android.hardware.gnss@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758495000-7007584ac000 r--p 0012e000 fe:00 1138                       /system/lib64/android.hardware.gnss@1.0.so
-Size:                 92 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  92 kB
-Pss:                  92 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        92 kB
-Referenced:           92 kB
-Anonymous:            92 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               92 kB
-VmFlags: rd mr mw me ac 
-7007584f4000-7007584f7000 r--p 00000000 fe:00 1550                       /system/lib64/libtinyalsa.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-7007584f7000-7007584fb000 r-xp 00003000 fe:00 1550                       /system/lib64/libtinyalsa.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007584fb000-7007584fc000 rw-p 00007000 fe:00 1550                       /system/lib64/libtinyalsa.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007584fc000-7007584fd000 r--p 00008000 fe:00 1550                       /system/lib64/libtinyalsa.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700758501000-70075850d000 r--p 00000000 fe:00 1197                       /system/lib64/android.hardware.power@1.1.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  15 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               15 kB
-VmFlags: rd mr mw me 
-70075850d000-700758519000 r-xp 0000c000 fe:00 1197                       /system/lib64/android.hardware.power@1.1.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  15 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               15 kB
-VmFlags: rd ex mr mw me 
-700758519000-70075851a000 rw-p 00018000 fe:00 1197                       /system/lib64/android.hardware.power@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075851a000-70075851c000 r--p 00019000 fe:00 1197                       /system/lib64/android.hardware.power@1.1.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758521000-700758541000 r--s 00000000 00:13 6676                       /dev/__properties__/u:object_r:bootloader_boot_reason_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700758541000-700758552000 r--p 00000000 fe:00 1517                       /system/lib64/libsensorservice.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        20 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me 
-700758552000-700758572000 r-xp 00011000 fe:00 1517                       /system/lib64/libsensorservice.so
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       128 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd ex mr mw me 
-700758572000-700758573000 rw-p 00031000 fe:00 1517                       /system/lib64/libsensorservice.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758573000-700758577000 r--p 00032000 fe:00 1517                       /system/lib64/libsensorservice.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me ac 
-700758577000-700758578000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758586000-700758591000 r--p 00000000 fe:00 1649                       /system/lib64/android.frameworks.schedulerservice@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700758591000-70075859b000 r-xp 0000b000 fe:00 1649                       /system/lib64/android.frameworks.schedulerservice@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                  40 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        40 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               40 kB
-VmFlags: rd ex mr mw me 
-70075859b000-70075859c000 rw-p 00015000 fe:00 1649                       /system/lib64/android.frameworks.schedulerservice@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075859c000-70075859e000 r--p 00016000 fe:00 1649                       /system/lib64/android.frameworks.schedulerservice@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007585ae000-7007585ce000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007585ce000-7007585d1000 r--p 00000000 fe:00 1634                       /system/lib64/libnetutils.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007585d1000-7007585d5000 r-xp 00003000 fe:00 1634                       /system/lib64/libnetutils.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007585d5000-7007585d6000 rw-p 00007000 fe:00 1634                       /system/lib64/libnetutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007585d6000-7007585d7000 r--p 00008000 fe:00 1634                       /system/lib64/libnetutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007585d7000-7007585d8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007585e6000-7007585e7000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007585e7000-7007585ef000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007585ef000-7007585f0000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007585f0000-7007585f3000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007585f3000-7007585f4000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007585f4000-7007585fc000 rw-s 00000000 fe:10 24584                      /data/system_ce/0/accounts_ce.db-shm
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr sh mr mw me ms 
-7007585fc000-7007585fd000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007585fd000-700758605000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758605000-70075862a000 r--p 00000000 fe:00 1626                       /system/lib64/android.hardware.broadcastradio@1.1.so
-Size:                148 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                  68 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        68 kB
-Private_Dirty:         0 kB
-Referenced:           68 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               68 kB
-VmFlags: rd mr mw me 
-70075862a000-70075865c000 r-xp 00025000 fe:00 1626                       /system/lib64/android.hardware.broadcastradio@1.1.so
-Size:                200 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 196 kB
-Pss:                 196 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       196 kB
-Private_Dirty:         0 kB
-Referenced:          196 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              196 kB
-VmFlags: rd ex mr mw me 
-70075865c000-70075865d000 rw-p 00057000 fe:00 1626                       /system/lib64/android.hardware.broadcastradio@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075865d000-700758664000 r--p 00058000 fe:00 1626                       /system/lib64/android.hardware.broadcastradio@1.1.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        28 kB
-Referenced:           28 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd mr mw me ac 
-700758666000-700758667000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700758667000-70075866f000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075866f000-700758674000 r--s 004e8000 fe:00 1805                       /system/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  10 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr me ms 
-70075869d000-7007586a6000 r--p 00000000 fe:00 1249                       /system/lib64/libinputservice.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  24 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        24 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd mr mw me 
-7007586a6000-7007586ad000 r-xp 00009000 fe:00 1249                       /system/lib64/libinputservice.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007586ad000-7007586ae000 rw-p 00010000 fe:00 1249                       /system/lib64/libinputservice.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007586ae000-7007586af000 r--p 00011000 fe:00 1249                       /system/lib64/libinputservice.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007586b2000-7007586b3000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007586b3000-7007586b6000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007586b6000-7007586b7000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007586d2000-7007586df000 r--p 00000000 fe:00 1211                       /system/lib64/android.hardware.sensors@1.0.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-7007586df000-7007586f1000 r-xp 0000d000 fe:00 1211                       /system/lib64/android.hardware.sensors@1.0.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                  72 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        72 kB
-Private_Dirty:         0 kB
-Referenced:           72 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               72 kB
-VmFlags: rd ex mr mw me 
-7007586f1000-7007586f2000 rw-p 0001f000 fe:00 1211                       /system/lib64/android.hardware.sensors@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007586f2000-7007586f4000 r--p 00020000 fe:00 1211                       /system/lib64/android.hardware.sensors@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007586f4000-7007586f5000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007586f5000-7007586f8000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007586f8000-7007586f9000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758721000-70075872e000 r--p 00000000 fe:00 1212                       /system/lib64/libkeystore_binder.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  17 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               17 kB
-VmFlags: rd mr mw me 
-70075872e000-700758739000 r-xp 0000d000 fe:00 1212                       /system/lib64/libkeystore_binder.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  14 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd ex mr mw me 
-700758739000-70075873a000 rw-p 00018000 fe:00 1212                       /system/lib64/libkeystore_binder.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075873a000-70075873d000 r--p 00019000 fe:00 1212                       /system/lib64/libkeystore_binder.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-70075873d000-70075873e000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758740000-700758742000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758742000-700758754000 r--p 00000000 fe:00 1521                       /system/lib64/android.hardware.contexthub@1.0.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-700758754000-70075876e000 r-xp 00012000 fe:00 1521                       /system/lib64/android.hardware.contexthub@1.0.so
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 100 kB
-Pss:                 100 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       100 kB
-Private_Dirty:         0 kB
-Referenced:          100 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              100 kB
-VmFlags: rd ex mr mw me 
-70075876e000-70075876f000 rw-p 0002c000 fe:00 1521                       /system/lib64/android.hardware.contexthub@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075876f000-700758772000 r--p 0002d000 fe:00 1521                       /system/lib64/android.hardware.contexthub@1.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-7007587a6000-7007587a8000 r--p 00000000 fe:00 1270                       /system/lib64/libschedulerservicehidl.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007587a8000-7007587a9000 r-xp 00002000 fe:00 1270                       /system/lib64/libschedulerservicehidl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me 
-7007587a9000-7007587aa000 rw-p 00003000 fe:00 1270                       /system/lib64/libschedulerservicehidl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007587aa000-7007587ab000 r--p 00004000 fe:00 1270                       /system/lib64/libschedulerservicehidl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007587ab000-7007587ae000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587ae000-7007587af000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587af000-7007587b2000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587b2000-7007587b3000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587b3000-7007587b6000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587b6000-7007587b7000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587b7000-7007587ba000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587ba000-7007587bb000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587bb000-7007587be000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587be000-7007587bf000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587bf000-7007587c2000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587c2000-7007587c3000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587c3000-7007587cd000 r--p 00000000 fe:00 1157                       /system/lib64/android.hardware.light@2.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-7007587cd000-7007587d7000 r-xp 0000a000 fe:00 1157                       /system/lib64/android.hardware.light@2.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                  40 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        40 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               40 kB
-VmFlags: rd ex mr mw me 
-7007587d7000-7007587d8000 rw-p 00014000 fe:00 1157                       /system/lib64/android.hardware.light@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007587d8000-7007587da000 r--p 00015000 fe:00 1157                       /system/lib64/android.hardware.light@2.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007587db000-7007587dd000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587dd000-7007587e0000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587e0000-7007587e1000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587e1000-7007587e4000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587e4000-7007587e5000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587e5000-7007587e8000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587e8000-7007587e9000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587e9000-7007587ec000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587ec000-7007587ed000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007587ed000-7007587f0000 r-xp 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me ac 
-7007587f0000-7007587f1000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758808000-700758814000 r--p 00000000 fe:00 1677                       /system/lib64/android.hardware.vibrator@1.2.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-700758814000-70075881f000 r-xp 0000c000 fe:00 1677                       /system/lib64/android.hardware.vibrator@1.2.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  44 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        44 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               44 kB
-VmFlags: rd ex mr mw me 
-70075881f000-700758820000 rw-p 00017000 fe:00 1677                       /system/lib64/android.hardware.vibrator@1.2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758820000-700758822000 r--p 00018000 fe:00 1677                       /system/lib64/android.hardware.vibrator@1.2.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758830000-700758850000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        32 kB
-Referenced:           32 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd wr mr mw me ac 
-700758850000-700758858000 r--p 00000000 fe:00 1546                       /system/lib64/libsensorservicehidl.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  24 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        24 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd mr mw me 
-700758858000-70075885c000 r-xp 00008000 fe:00 1546                       /system/lib64/libsensorservicehidl.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd ex mr mw me 
-70075885c000-70075885d000 rw-p 0000c000 fe:00 1546                       /system/lib64/libsensorservicehidl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075885d000-70075885f000 r--p 0000d000 fe:00 1546                       /system/lib64/libsensorservicehidl.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758860000-700758880000 r--s 00000000 00:13 6738                       /dev/__properties__/u:object_r:system_boot_reason_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700758880000-700758897000 r--p 00000000 fe:00 1225                       /system/lib64/libkeystore_aidl.so
-Size:                 92 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  92 kB
-Pss:                  32 kB
-Shared_Clean:         92 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           92 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr mw me 
-700758897000-7007588a4000 r-xp 00017000 fe:00 1225                       /system/lib64/libkeystore_aidl.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  17 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               17 kB
-VmFlags: rd ex mr mw me 
-7007588a4000-7007588a5000 rw-p 00024000 fe:00 1225                       /system/lib64/libkeystore_aidl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007588a5000-7007588ad000 r--p 00025000 fe:00 1225                       /system/lib64/libkeystore_aidl.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        32 kB
-Referenced:           32 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr mw me ac 
-7007588ad000-7007588ae000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007588ae000-7007588b0000 r-xp 00000000 00:00 0 
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd ex mr mw me ac 
-7007588b0000-7007588d0000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-7007588d0000-7007588d6000 r--p 00000000 fe:00 1704                       /system/lib64/libkeystore_parcelables.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   7 kB
-Shared_Clean:         24 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007588d6000-7007588da000 r-xp 00006000 fe:00 1704                       /system/lib64/libkeystore_parcelables.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007588da000-7007588db000 rw-p 0000a000 fe:00 1704                       /system/lib64/libkeystore_parcelables.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007588db000-7007588dc000 r--p 0000b000 fe:00 1704                       /system/lib64/libkeystore_parcelables.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007588dd000-7007588de000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007588de000-7007588e6000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007588e6000-700758906000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700758906000-70075890e000 rw-s 00000000 fe:10 188581                     /data/system/notification_log.db-shm
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr sh mr mw me ms 
-70075890e000-70075892d000 r--p 00000000 fe:00 1578                       /system/lib64/android.hardware.broadcastradio@1.0.so
-Size:                124 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-70075892d000-70075895a000 r-xp 0001f000 fe:00 1578                       /system/lib64/android.hardware.broadcastradio@1.0.so
-Size:                180 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 176 kB
-Pss:                 176 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       176 kB
-Private_Dirty:         0 kB
-Referenced:          176 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              176 kB
-VmFlags: rd ex mr mw me 
-70075895a000-70075895b000 rw-p 0004c000 fe:00 1578                       /system/lib64/android.hardware.broadcastradio@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075895b000-700758961000 r--p 0004d000 fe:00 1578                       /system/lib64/android.hardware.broadcastradio@1.0.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  24 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        24 kB
-Referenced:           24 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd mr mw me ac 
-700758961000-700758962000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758962000-700758965000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758965000-700758966000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758966000-700758968000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758983000-700758984000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700758984000-70075898c000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075898c000-70075898d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075898d000-700758990000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700758990000-700758991000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758991000-700758993000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007589b3000-7007589b4000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007589b4000-7007589bc000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007589bc000-7007589f8000 r--p 00000000 fe:00 1622                       /system/lib64/libandroid_servers.so
-Size:                240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 100 kB
-Pss:                 100 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       100 kB
-Private_Dirty:         0 kB
-Referenced:          100 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              100 kB
-VmFlags: rd mr mw me 
-7007589f8000-700758a36000 r-xp 0003c000 fe:00 1622                       /system/lib64/libandroid_servers.so
-Size:                248 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 244 kB
-Pss:                 244 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       244 kB
-Private_Dirty:         0 kB
-Referenced:          244 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              244 kB
-VmFlags: rd ex mr mw me 
-700758a36000-700758a37000 rw-p 0007a000 fe:00 1622                       /system/lib64/libandroid_servers.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758a37000-700758a3f000 r--p 0007b000 fe:00 1622                       /system/lib64/libandroid_servers.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        32 kB
-Referenced:           32 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr mw me ac 
-700758a3f000-700758a40000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758a40000-700758a41000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700758a41000-700758a49000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758a49000-700758a4a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700758a4a000-700758a52000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758a52000-700758a5c000 r--p 00000000 fe:00 1507                       /system/lib64/android.hardware.ir@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700758a5c000-700758a66000 r-xp 0000a000 fe:00 1507                       /system/lib64/android.hardware.ir@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                  40 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        40 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               40 kB
-VmFlags: rd ex mr mw me 
-700758a66000-700758a67000 rw-p 00014000 fe:00 1507                       /system/lib64/android.hardware.ir@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758a67000-700758a69000 r--p 00015000 fe:00 1507                       /system/lib64/android.hardware.ir@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700758a69000-700758a6a000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758a6a000-700758a6d000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758a6d000-700758a6e000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758a6e000-700758a8e000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                  36 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        36 kB
-Referenced:           36 kB
-Anonymous:            36 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               36 kB
-VmFlags: rd wr mr mw me ac 
-700758a8e000-700758a8f000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700758a8f000-700758a90000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700758a90000-700758b88000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me nr 
-700758b88000-700758b89000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700758b89000-700758b8a000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-700758b8a000-700758c82000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me nr 
-700758c82000-700758c85000 r--p 00000000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-700758c85000-700758c89000 r-xp 00003000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700758c89000-700758c8a000 r--p 00007000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700758c8a000-700758c8b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758c8b000-700758c90000 r--s 00000000 fe:00 3249                       /system/framework/oat/x86_64/com.android.location.provider.impl.vdex
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  10 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr me ms 
-700758c90000-700758c91000 r--p 00008000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-700758c91000-700758c92000 rw-p 00009000 fe:00 3277                       /system/framework/oat/x86_64/com.android.location.provider.impl.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700758c93000-700758c94000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758c94000-700758c97000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758c97000-700758c98000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700758c98000-700758c99000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700758c99000-700758ca1000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758ca1000-700758ca2000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700758ca2000-700758caa000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700758caa000-700758cca000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-700758cca000-700758d93000 r--p 00000000 fe:00 3287                       /system/framework/oat/x86_64/wifi-service.odex
-Size:                804 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 116 kB
-Pss:                 116 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       116 kB
-Private_Dirty:         0 kB
-Referenced:          116 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              116 kB
-VmFlags: rd mr mw me 
-700758d93000-70075910d000 r-xp 000c9000 fe:00 3287                       /system/framework/oat/x86_64/wifi-service.odex
-Size:               3560 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                3184 kB
-Pss:                3184 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:      3184 kB
-Private_Dirty:         0 kB
-Referenced:         3184 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             3184 kB
-VmFlags: rd ex mr mw me 
-70075910d000-70075910f000 r--p 00443000 fe:00 3287                       /system/framework/oat/x86_64/wifi-service.odex
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-70075910f000-700759118000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                  36 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        36 kB
-Referenced:           36 kB
-Anonymous:            36 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               36 kB
-VmFlags: rd wr mr mw me ac 
-700759118000-70075932e000 r--s 00000000 fe:00 3231                       /system/framework/oat/x86_64/wifi-service.vdex
-Size:               2136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  64 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        64 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               64 kB
-VmFlags: rd mr me ms 
-70075932e000-70075932f000 r--p 00445000 fe:00 3287                       /system/framework/oat/x86_64/wifi-service.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-70075932f000-700759330000 rw-p 00446000 fe:00 3287                       /system/framework/oat/x86_64/wifi-service.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700759330000-700759332000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700759332000-700759348000 r--s 00602000 fe:00 1821                       /system/priv-app/Telecom/Telecom.apk
-Size:                 88 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  88 kB
-Pss:                  88 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        88 kB
-Private_Dirty:         0 kB
-Referenced:           88 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               88 kB
-VmFlags: rd mr me ms 
-700759348000-700759349000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700759349000-700759351000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700759351000-700759355000 r--p 00000000 fe:00 3250                       /system/framework/oat/x86_64/ethernet-service.odex
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        16 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700759355000-700759361000 r-xp 00004000 fe:00 3250                       /system/framework/oat/x86_64/ethernet-service.odex
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  48 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        48 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               48 kB
-VmFlags: rd ex mr mw me 
-700759361000-700759362000 r--p 00010000 fe:00 3250                       /system/framework/oat/x86_64/ethernet-service.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700759362000-700759363000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700759363000-70075936b000 r--s 00000000 fe:00 3243                       /system/framework/oat/x86_64/ethernet-service.vdex
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        32 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr me ms 
-70075936b000-70075936c000 r--p 00011000 fe:00 3250                       /system/framework/oat/x86_64/ethernet-service.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-70075936c000-70075936d000 rw-p 00012000 fe:00 3250                       /system/framework/oat/x86_64/ethernet-service.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075936d000-70075936f000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075936f000-700759370000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700759370000-700759373000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700759373000-700759375000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700759375000-700759378000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700759378000-700759379000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700759379000-70075937a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70075937a000-700759382000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700759382000-700759383000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700759383000-700759386000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700759386000-700759387000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700759387000-70075983a000 r--p 00000000 fe:00 3248                       /system/framework/oat/x86_64/services.odex
-Size:               4812 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2576 kB
-Pss:                2576 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:      2576 kB
-Private_Dirty:         0 kB
-Referenced:         2576 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2576 kB
-VmFlags: rd mr mw me 
-70075983a000-70075a9b3000 r-xp 004b3000 fe:00 3248                       /system/framework/oat/x86_64/services.odex
-Size:              17892 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               17060 kB
-Pss:               17060 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:     17060 kB
-Private_Dirty:         0 kB
-Referenced:        17060 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:            17060 kB
-VmFlags: rd ex mr mw me 
-70075a9b3000-70075a9ba000 r--p 0162c000 fe:00 3248                       /system/framework/oat/x86_64/services.odex
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        28 kB
-Referenced:           28 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd mr mw me ac 
-70075a9ba000-70075a9e2000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 160 kB
-Pss:                 160 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       160 kB
-Referenced:          160 kB
-Anonymous:           160 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              160 kB
-VmFlags: rd wr mr mw me ac 
-70075a9e2000-70075b335000 r--s 00000000 fe:00 3271                       /system/framework/oat/x86_64/services.vdex
-Size:               9548 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2856 kB
-Pss:                2856 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:      2856 kB
-Private_Dirty:         0 kB
-Referenced:         2856 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2856 kB
-VmFlags: rd mr me ms 
-70075b335000-70075b336000 r--p 01633000 fe:00 3248                       /system/framework/oat/x86_64/services.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-70075b336000-70075b337000 rw-p 01634000 fe:00 3248                       /system/framework/oat/x86_64/services.odex
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075b338000-70075b33a000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b33a000-70075b33b000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70075b33b000-70075b343000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b344000-70075b346000 r-xp 00000000 00:00 0 
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd ex mr mw me ac 
-70075b34b000-70075b34c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075b34c000-70075b34f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b34f000-70075b350000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075b350000-70075b352000 r-xp 00000000 00:00 0 
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd ex mr mw me ac 
-70075b354000-70075b355000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075b355000-70075b358000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b358000-70075b359000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075b359000-70075b35a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70075b35a000-70075b362000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b362000-70075b363000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075b363000-70075b366000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b366000-70075b367000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70075b367000-70075b369000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70075b369000-70075b36a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70075b36a000-70075b372000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b372000-70075b373000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70075b373000-70075b37b000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70075b37b000-70075b479000 r--p 00000000 00:13 6783                       /dev/binder
-Size:               1016 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  24 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        24 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd mr me dc nr mm 
-70075b479000-70075b47a000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b47a000-70075b47b000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b47b000-70075b57f000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075b57f000-70075b580000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b580000-70075b581000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b581000-70075b685000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70075b685000-70075b686000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b686000-70075b687000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b687000-70075b78b000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me nr 
-70075b78b000-70075b78c000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b78c000-70075b78d000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70075b78d000-70075b891000 rw-p 00000000 00:00 0 
-Size:               1040 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70075b891000-70075d891000 r--s 02000000 00:05 9572                       /memfd:/jit-cache (deleted)
-Size:              32768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd sh mr mw me ms 
-70075d891000-700766592000 ---p 00000000 00:00 0 
-Size:             144388 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766592000-700766593000 r--p 00000000 fe:00 1106                       /system/lib64/libwebviewchromium_loader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-700766593000-700766594000 r-xp 00001000 fe:00 1106                       /system/lib64/libwebviewchromium_loader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700766594000-700766595000 rw-p 00002000 fe:00 1106                       /system/lib64/libwebviewchromium_loader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766595000-700766596000 r--p 00003000 fe:00 1106                       /system/lib64/libwebviewchromium_loader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766596000-700766597000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766597000-700766598000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766598000-7007665a0000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665a0000-7007665a1000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665a1000-7007665a4000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665a4000-7007665a5000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665a5000-7007665a9000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007665ab000-7007665af000 r--s 00002000 fe:00 2036                       /system/priv-app/FusedLocation/FusedLocation.apk
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  14 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd mr me ms 
-7007665af000-7007665b2000 r--p 00000000 fe:00 2036                       /system/priv-app/FusedLocation/FusedLocation.apk
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  10 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me ac 
-7007665b5000-7007665b7000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007665b7000-7007665b8000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665b8000-7007665bb000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665bb000-7007665bc000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665bc000-7007665be000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007665be000-7007665bf000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007665bf000-7007665c7000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665c7000-7007665c8000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007665c8000-7007665d0000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665d0000-7007665d1000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665d1000-7007665d4000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665d4000-7007665d6000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665d6000-7007665d9000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665d9000-7007665da000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007665da000-7007665db000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007665db000-7007665e3000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665e3000-7007665e4000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007665e4000-7007665ec000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665ed000-7007665ef000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665ef000-7007665f0000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007665f0000-7007665f8000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007665f8000-700766646000 r--s 00000000 fe:00 1030                       /system/usr/hyphen-data/hyph-hu.hyb
-Size:                312 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700766646000-70076664f000 r--p 00000000 fe:00 1712                       /system/lib64/libcompiler_rt.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   9 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-70076664f000-700766664000 r-xp 00009000 fe:00 1712                       /system/lib64/libcompiler_rt.so
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700766664000-700766665000 rw-p 0001e000 fe:00 1712                       /system/lib64/libcompiler_rt.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766665000-700766666000 r--p 0001f000 fe:00 1712                       /system/lib64/libcompiler_rt.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766666000-700766690000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                168 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766691000-700766699000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700766699000-70076669b000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076669b000-70076669c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076669c000-70076669f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076669f000-7007666a0000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007666a0000-7007666b0000 rw-s 00000000 00:05 11661                      /dev/ashmem/RemoteDataSource (deleted)
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr sh mr mw me ms 
-7007666b0000-7007666b1000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007666b1000-7007666b9000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007666b9000-7007666ba000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007666ba000-7007666bd000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007666bd000-7007666be000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007666be000-7007666c0000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007666c0000-700766751000 r--p 00000000 fe:30 333                        /vendor/lib64/egl/libGLESv1_CM_swiftshader.so
-Size:                580 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 192 kB
-Pss:                  38 kB
-Shared_Clean:        192 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          192 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               38 kB
-VmFlags: rd mr mw me 
-700766751000-70076690e000 r-xp 00091000 fe:30 333                        /vendor/lib64/egl/libGLESv1_CM_swiftshader.so
-Size:               1780 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 116 kB
-Pss:                  24 kB
-Shared_Clean:        116 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          116 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd ex mr mw me 
-70076690e000-70076690f000 rw-p 0024e000 fe:30 333                        /vendor/lib64/egl/libGLESv1_CM_swiftshader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076690f000-70076691f000 r--p 0024f000 fe:30 333                        /vendor/lib64/egl/libGLESv1_CM_swiftshader.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         64 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:            64 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-70076691f000-70076696d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                312 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 312 kB
-Pss:                  17 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        312 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:           312 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               17 kB
-VmFlags: rd wr mr mw me ac 
-70076696d000-70076696e000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076696e000-700766976000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766976000-700766977000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766977000-70076697f000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076697f000-700766980000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766980000-700766983000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766983000-700766985000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766985000-700766988000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766988000-70076698a000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076698a000-70076698d000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076698d000-70076698f000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076698f000-700766992000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766992000-700766993000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766993000-700766994000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766994000-70076699c000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076699c000-700766a5f000 r--p 00000000 fe:30 335                        /vendor/lib64/egl/libGLESv2_swiftshader.so
-Size:                780 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                  51 kB
-Shared_Clean:        256 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          256 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               51 kB
-VmFlags: rd mr mw me 
-700766a5f000-700766c8d000 r-xp 000c3000 fe:30 335                        /vendor/lib64/egl/libGLESv2_swiftshader.so
-Size:               2232 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2212 kB
-Pss:                 624 kB
-Shared_Clean:       2212 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2212 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              624 kB
-VmFlags: rd ex mr mw me 
-700766c8d000-700766c8e000 rw-p 002f1000 fe:30 335                        /vendor/lib64/egl/libGLESv2_swiftshader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700766c8e000-700766ca2000 r--p 002f2000 fe:30 335                        /vendor/lib64/egl/libGLESv2_swiftshader.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         80 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:            80 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700766ca2000-700766cf0000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                312 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 312 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        296 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           44 kB
-Anonymous:           312 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd wr mr mw me ac 
-700766cf1000-700766cf3000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766cf3000-700766cf4000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766cf4000-700766cf7000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766cf7000-700766cf9000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766cf9000-700766cfc000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766cfc000-700766cfd000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766cfd000-700766cfe000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766cfe000-700766d06000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766d06000-700766d13000 r--p 00000000 fe:30 334                        /vendor/lib64/egl/libEGL_swiftshader.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  10 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-700766d13000-700766d2f000 r-xp 0000d000 fe:30 334                        /vendor/lib64/egl/libEGL_swiftshader.so
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 112 kB
-Pss:                  22 kB
-Shared_Clean:        112 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          112 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               22 kB
-VmFlags: rd ex mr mw me 
-700766d2f000-700766d30000 rw-p 00029000 fe:30 334                        /vendor/lib64/egl/libEGL_swiftshader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766d30000-700766d31000 r--p 0002a000 fe:30 334                        /vendor/lib64/egl/libEGL_swiftshader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766d31000-700766d78000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                284 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 284 kB
-Pss:                  19 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        280 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:           284 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               19 kB
-VmFlags: rd wr mr mw me ac 
-700766d78000-700766d7e000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-700766d7e000-700766d7f000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766d7f000-700766d82000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766d82000-700766d83000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766d83000-700766d84000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766d84000-700766d8c000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766d8c000-700766d8d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766d8d000-700766d90000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766d90000-700766d91000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766d91000-700766db1000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                 124 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       124 kB
-Referenced:          124 kB
-Anonymous:           124 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              124 kB
-VmFlags: rd wr mr mw me ac 
-700766db1000-700766db3000 r--p 00000000 fe:00 1488                       /system/lib64/vndk-sp-Q/libbinderthreadstate.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-700766db3000-700766db5000 r-xp 00002000 fe:00 1488                       /system/lib64/vndk-sp-Q/libbinderthreadstate.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700766db5000-700766db6000 rw-p 00004000 fe:00 1488                       /system/lib64/vndk-sp-Q/libbinderthreadstate.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766db6000-700766db7000 r--p 00005000 fe:00 1488                       /system/lib64/vndk-sp-Q/libbinderthreadstate.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766db7000-700766db8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766db8000-700766dbc000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700766dbc000-700766dbd000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766dbd000-700766dc5000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766dc5000-700766dc6000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766dc6000-700766dce000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766dce000-700766e26000 r--p 00000000 fe:00 1497                       /system/lib64/vndk-sp-Q/libc++.so
-Size:                352 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 252 kB
-Pss:                  11 kB
-Shared_Clean:        252 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          252 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               11 kB
-VmFlags: rd mr mw me 
-700766e26000-700766e9a000 r-xp 00058000 fe:00 1497                       /system/lib64/vndk-sp-Q/libc++.so
-Size:                464 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 408 kB
-Pss:                  18 kB
-Shared_Clean:        408 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          408 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               18 kB
-VmFlags: rd ex mr mw me 
-700766e9a000-700766e9b000 rw-p 000cc000 fe:00 1497                       /system/lib64/vndk-sp-Q/libc++.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766e9b000-700766ea3000 r--p 000cd000 fe:00 1497                       /system/lib64/vndk-sp-Q/libc++.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         32 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700766ea3000-700766ea7000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-700766ea8000-700766ea9000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766ea9000-700766eac000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766eac000-700766ead000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766ead000-700766eae000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766eae000-700766eb6000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766eb6000-700766ed6000 r--s 00000000 00:13 6703                       /dev/__properties__/u:object_r:device_logging_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr me ms 
-700766ed6000-700766ee9000 r--p 00000000 fe:00 1476                       /system/lib64/vndk-sp-Q/libhwbinder.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-700766ee9000-700766efa000 r-xp 00013000 fe:00 1476                       /system/lib64/vndk-sp-Q/libhwbinder.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700766efa000-700766efb000 rw-p 00024000 fe:00 1476                       /system/lib64/vndk-sp-Q/libhwbinder.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766efb000-700766efd000 r--p 00025000 fe:00 1476                       /system/lib64/vndk-sp-Q/libhwbinder.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766efd000-700766efe000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766eff000-700766f01000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700766f01000-700766f02000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f02000-700766f05000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f05000-700766f07000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f07000-700766f0a000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f0a000-700766f0b000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f0c000-700766f0d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f0d000-700766f10000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f10000-700766f11000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f11000-700766f13000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700766f13000-700766f14000 r--p 00000000 fe:00 1492                       /system/lib64/vndk-sp-Q/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-700766f14000-700766f15000 r-xp 00001000 fe:00 1492                       /system/lib64/vndk-sp-Q/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700766f15000-700766f16000 rw-p 00002000 fe:00 1492                       /system/lib64/vndk-sp-Q/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f16000-700766f17000 r--p 00003000 fe:00 1492                       /system/lib64/vndk-sp-Q/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766f17000-700766f37000 r--s 00000000 00:13 6734                       /dev/__properties__/u:object_r:safemode_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700766f37000-700766f57000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-700766f57000-700766f63000 r--p 00000000 fe:00 1491                       /system/lib64/vndk-sp-Q/android.hardware.graphics.mapper@2.0.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   6 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-700766f63000-700766f6f000 r-xp 0000c000 fe:00 1491                       /system/lib64/vndk-sp-Q/android.hardware.graphics.mapper@2.0.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   6 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-700766f6f000-700766f70000 rw-p 00018000 fe:00 1491                       /system/lib64/vndk-sp-Q/android.hardware.graphics.mapper@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f70000-700766f72000 r--p 00019000 fe:00 1491                       /system/lib64/vndk-sp-Q/android.hardware.graphics.mapper@2.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766f72000-700766f74000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700766f74000-700766f75000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766f75000-700766f7d000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f7d000-700766f7e000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f7e000-700766f81000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f81000-700766f82000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766f82000-700766f83000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766f83000-700766f8b000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f8b000-700766f8e000 r--p 00000000 fe:30 348                        /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   1 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700766f8e000-700766f91000 r-xp 00003000 fe:30 348                        /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   2 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-700766f91000-700766f92000 rw-p 00006000 fe:30 348                        /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766f92000-700766f93000 r--p 00007000 fe:30 348                        /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766f93000-700766f94000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700766f95000-700766f99000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700766f99000-700766f9a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766f9a000-700766fa2000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766fa2000-700766fa3000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700766fa3000-700766fab000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766fab000-700766fcb000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-700766fcb000-700766fd2000 r--p 00000000 fe:00 1487                       /system/lib64/vndk-sp-Q/libcutils.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   1 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700766fd2000-700766fdb000 r-xp 00007000 fe:00 1487                       /system/lib64/vndk-sp-Q/libcutils.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   2 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-700766fdb000-700766fdc000 rw-p 00010000 fe:00 1487                       /system/lib64/vndk-sp-Q/libcutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766fdc000-700766fde000 r--p 00011000 fe:00 1487                       /system/lib64/vndk-sp-Q/libcutils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700766fde000-700766fdf000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766fe0000-700766fe1000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766fe1000-700766fe4000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700766fe4000-700766fe5000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700766fe5000-700767005000 r--s 00000000 00:13 6741                       /dev/__properties__/u:object_r:system_radio_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700767005000-70076700e000 r--p 00000000 fe:00 1503                       /system/lib64/vndk-sp-Q/libbase.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   1 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-70076700e000-700767017000 r-xp 00009000 fe:00 1503                       /system/lib64/vndk-sp-Q/libbase.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700767017000-700767018000 rw-p 00012000 fe:00 1503                       /system/lib64/vndk-sp-Q/libbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767018000-700767019000 r--p 00013000 fe:00 1503                       /system/lib64/vndk-sp-Q/libbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700767019000-70076701a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076701b000-70076701d000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076701d000-70076701e000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076701e000-700767026000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767026000-700767027000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767027000-70076702a000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076702a000-70076702b000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076702b000-70076702c000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076702c000-700767034000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767034000-700767035000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767035000-700767038000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767038000-700767039000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767039000-70076703a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076703a000-700767042000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767042000-700767043000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700767043000-70076704b000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076704b000-70076705a000 r--p 00000000 fe:00 1478                       /system/lib64/vndk-sp-Q/libutils.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   2 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-70076705a000-700767066000 r-xp 0000f000 fe:00 1478                       /system/lib64/vndk-sp-Q/libutils.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   2 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-700767066000-700767067000 rw-p 0001b000 fe:00 1478                       /system/lib64/vndk-sp-Q/libutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767067000-700767068000 r--p 0001c000 fe:00 1478                       /system/lib64/vndk-sp-Q/libutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700767068000-700767069000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076706a000-70076706c000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076706c000-70076706d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076706d000-700767070000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767070000-700767072000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767072000-700767075000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767075000-700767077000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767077000-70076707a000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076707a000-70076707b000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076707b000-70076707c000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076707c000-700767084000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767084000-700767085000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700767085000-70076708d000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076708e000-700767094000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700767094000-700767095000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767095000-700767098000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767098000-700767099000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767099000-70076709b000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076709b000-7007670d4000 r--p 00000000 fe:00 1489                       /system/lib64/vndk-sp-Q/libhidltransport.so
-Size:                228 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 148 kB
-Pss:                  10 kB
-Shared_Clean:        148 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          148 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007670d4000-70076712f000 r-xp 00039000 fe:00 1489                       /system/lib64/vndk-sp-Q/libhidltransport.so
-Size:                364 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 236 kB
-Pss:                  13 kB
-Shared_Clean:        236 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          236 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               13 kB
-VmFlags: rd ex mr mw me 
-70076712f000-700767130000 rw-p 00094000 fe:00 1489                       /system/lib64/vndk-sp-Q/libhidltransport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767130000-70076713a000 r--p 00095000 fe:00 1489                       /system/lib64/vndk-sp-Q/libhidltransport.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         40 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:            40 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me ac 
-70076713a000-70076713b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076713b000-70076713c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076713c000-70076713f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076713f000-700767141000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767141000-700767144000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767144000-700767145000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767145000-700767146000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700767146000-70076714e000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076714e000-70076714f000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076714f000-700767152000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767152000-700767153000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700767153000-700767154000 r--p 00000000 fe:00 1495                       /system/lib64/vndk-sp-Q/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-700767154000-700767155000 r-xp 00001000 fe:00 1495                       /system/lib64/vndk-sp-Q/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700767155000-700767156000 rw-p 00002000 fe:00 1495                       /system/lib64/vndk-sp-Q/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700767156000-700767157000 r--p 00003000 fe:00 1495                       /system/lib64/vndk-sp-Q/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700767157000-700767197000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 152 kB
-Pss:                 152 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       152 kB
-Referenced:          152 kB
-Anonymous:           152 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              152 kB
-VmFlags: rd wr mr mw me ac 
-700767197000-7007671a6000 r--p 00000000 fe:00 1477                       /system/lib64/vndk-sp-Q/libhidlbase.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   3 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007671a6000-7007671b9000 r-xp 0000f000 fe:00 1477                       /system/lib64/vndk-sp-Q/libhidlbase.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   1 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-7007671b9000-7007671ba000 rw-p 00022000 fe:00 1477                       /system/lib64/vndk-sp-Q/libhidlbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007671ba000-7007671bc000 r--p 00023000 fe:00 1477                       /system/lib64/vndk-sp-Q/libhidlbase.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007671bc000-7007671bd000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007671bd000-7007671bf000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007671bf000-7007671c0000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007671c0000-7007671c8000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007671c8000-7007671c9000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007671c9000-7007671cc000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007671cc000-7007671cd000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007671cd000-7007671ce000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007671ce000-7007671d6000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007671d6000-7007671d7000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007671d7000-7007671da000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007671da000-7007671db000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007671db000-700768d59000 r--s 00bc3000 fe:00 3346                       /system/framework/framework-res.apk
-Size:              28152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               19968 kB
-Pss:                1144 kB
-Shared_Clean:      19956 kB
-Shared_Dirty:          0 kB
-Private_Clean:        12 kB
-Private_Dirty:         0 kB
-Referenced:        19968 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1144 kB
-VmFlags: rd mr me ms 
-700768d59000-700768e14000 r--s 0287a000 fe:00 3346                       /system/framework/framework-res.apk
-Size:                748 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 144 kB
-Pss:                  18 kB
-Shared_Clean:        144 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          144 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               18 kB
-VmFlags: rd mr me ms 
-700768e14000-700768e35000 r--p 00000000 fe:00 1638                       /system/lib64/libssl.so
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 108 kB
-Pss:                  38 kB
-Shared_Clean:        108 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          108 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               38 kB
-VmFlags: rd mr mw me 
-700768e35000-700768e6c000 r-xp 00021000 fe:00 1638                       /system/lib64/libssl.so
-Size:                220 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 172 kB
-Pss:                  88 kB
-Shared_Clean:        168 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:          172 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               88 kB
-VmFlags: rd ex mr mw me 
-700768e6c000-700768e6d000 rw-p 00058000 fe:00 1638                       /system/lib64/libssl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768e6d000-700768e70000 r--p 00059000 fe:00 1638                       /system/lib64/libssl.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700768e70000-700768e74000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700768e74000-700768e75000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700768e75000-700768e7d000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768e7d000-700768e7e000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700768e7e000-700768e81000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768e81000-700768e82000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700768e82000-700768ea2000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-700768ea2000-700768ebf000 r--p 00000000 fe:00 1513                       /system/lib64/libjavacrypto.so
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 112 kB
-Pss:                  23 kB
-Shared_Clean:        112 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          112 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               23 kB
-VmFlags: rd mr mw me 
-700768ebf000-700768ee5000 r-xp 0001d000 fe:00 1513                       /system/lib64/libjavacrypto.so
-Size:                152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 152 kB
-Pss:                  27 kB
-Shared_Clean:        152 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          152 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               27 kB
-VmFlags: rd ex mr mw me 
-700768ee5000-700768ee7000 rw-p 00043000 fe:00 1513                       /system/lib64/libjavacrypto.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768ee7000-700768ee9000 r--p 00045000 fe:00 1513                       /system/lib64/libjavacrypto.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700768ee9000-700768eea000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768eea000-700768eeb000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700768eeb000-700768ef3000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768ef3000-700768ef4000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700768ef4000-700768efc000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768efc000-700768f1c000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-700768f1c000-700768f22000 r--p 00000000 fe:00 1763                       /system/lib64/libsoundpool.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   4 kB
-Shared_Clean:         24 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-700768f22000-700768f27000 r-xp 00006000 fe:00 1763                       /system/lib64/libsoundpool.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   6 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-700768f27000-700768f28000 rw-p 0000b000 fe:00 1763                       /system/lib64/libsoundpool.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768f28000-700768f29000 r--p 0000c000 fe:00 1763                       /system/lib64/libsoundpool.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700768f29000-700768f2a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768f2b000-700768f2c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700768f2c000-700768f2f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768f2f000-700768f31000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700768f31000-700768f34000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768f34000-700768f35000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700768f35000-700768f36000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700768f36000-700768f3e000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700768f3e000-700768f5e000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-700768f5e000-700768fd9000 r--s 00000000 07:08 15                         /apex/com.android.tzdata/etc/tz/tzdata
-Size:                492 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700768fd9000-700769748000 r--s 00000000 fe:00 100                        /system/fonts/NotoColorEmoji.ttf
-Size:               7612 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700769748000-70076aee5000 r--s 00000000 fe:00 130                        /system/fonts/NotoSerifCJK-Regular.ttc
-Size:              24180 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076aee5000-70076c0b5000 r--s 00000000 fe:00 239                        /system/fonts/NotoSansCJK-Regular.ttc
-Size:              18240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c0b5000-70076c163000 r--s 00000000 fe:00 161                        /system/fonts/NotoSansSymbols-Regular-Subsetted.ttf
-Size:                696 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c163000-70076c1bf000 r--s 00000000 fe:00 257                        /system/fonts/NotoSansTibetan-Bold.ttf
-Size:                368 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c1bf000-70076c222000 r--s 00000000 fe:00 270                        /system/fonts/NotoSansTibetan-Regular.ttf
-Size:                396 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c222000-70076c29e000 r--s 00000000 fe:00 254                        /system/fonts/NotoSansEgyptianHieroglyphs-Regular.ttf
-Size:                496 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c29e000-70076c319000 r--s 00000000 fe:00 196                        /system/fonts/NotoSansCuneiform-Regular.ttf
-Size:                492 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c319000-70076c36a000 r--s 00000000 fe:00 233                        /system/fonts/RobotoCondensed-BoldItalic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c36a000-70076c3b5000 r--s 00000000 fe:00 282                        /system/fonts/RobotoCondensed-Bold.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c3b5000-70076c406000 r--s 00000000 fe:00 288                        /system/fonts/RobotoCondensed-MediumItalic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c406000-70076c451000 r--s 00000000 fe:00 184                        /system/fonts/RobotoCondensed-Medium.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076c451000-70076c6d1000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               2560 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2452 kB
-Pss:                1171 kB
-Shared_Clean:          0 kB
-Shared_Dirty:       1356 kB
-Private_Clean:         0 kB
-Private_Dirty:      1096 kB
-Referenced:         1336 kB
-Anonymous:          2452 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1171 kB
-VmFlags: rd wr mr mw me ac 
-70076c6d1000-70076de00000 r--s 00000000 fe:00 1096                       /system/usr/icu/icudt63l.dat
-Size:              23740 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 452 kB
-Pss:                  85 kB
-Shared_Clean:        452 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          452 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               85 kB
-VmFlags: rd mr me ms 
-70076de00000-70076e200000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               4096 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                3988 kB
-Pss:                3677 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        336 kB
-Private_Clean:         0 kB
-Private_Dirty:      3652 kB
-Referenced:         3632 kB
-Anonymous:          3988 kB
-AnonHugePages:      2048 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             3677 kB
-VmFlags: rd wr mr mw me ac 
-70076e201000-70076e203000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076e203000-70076e204000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076e204000-70076e20c000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e20c000-70076e25d000 r--s 00000000 fe:00 182                        /system/fonts/RobotoCondensed-Italic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076e25d000-70076e2a7000 r--s 00000000 fe:00 96                         /system/fonts/RobotoCondensed-Regular.ttf
-Size:                296 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076e2a7000-70076e2f9000 r--s 00000000 fe:00 285                        /system/fonts/RobotoCondensed-LightItalic.ttf
-Size:                328 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70076e2f9000-70076e2fd000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-70076e2fd000-70076e2fe000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076e2fe000-70076e301000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e301000-70076e303000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076e303000-70076e306000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e306000-70076e307000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076e307000-70076e308000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076e308000-70076e310000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e310000-70076e311000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076e311000-70076e314000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e314000-70076e315000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076e315000-70076e316000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076e316000-70076e31e000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e31e000-70076e31f000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076e31f000-70076e327000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e327000-70076e328000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70076e328000-70076e329000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70076e329000-70076e421000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70076e421000-70076e422000 ---p 00000000 00:00 0                          [anon:thread stack guard]
-Name:           [anon:thread stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70076e422000-70076e423000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me nr 
-70076e423000-70076e51b000 rw-p 00000000 00:00 0 
-Size:                992 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me nr 
-70076e51b000-70076e51c000 ---p 00000000 00:00 0                          [anon:dalvik-Jit thread pool worker thread 0]
-Name:           [anon:dalvik-Jit thread pool worker thread 0]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076e51c000-70076e51d000 ---p 00000000 00:00 0                          [anon:dalvik-Jit thread pool worker thread 0]
-Name:           [anon:dalvik-Jit thread pool worker thread 0]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076e51d000-70076e61c000 rw-p 00000000 00:00 0                          [anon:dalvik-Jit thread pool worker thread 0]
-Name:           [anon:dalvik-Jit thread pool worker thread 0]
-Size:               1020 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                  28 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        28 kB
-Referenced:           28 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               28 kB
-VmFlags: rd wr mr mw me ac 
-70076e61c000-70076e717000 rw-p 00000000 00:00 0                          [anon:dalvik-allocspace non moving space mark-bitmap 1]
-Name:           [anon:dalvik-allocspace non moving space mark-bitmap 1]
-Size:               1004 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076e717000-70076e812000 rw-p 00000000 00:00 0                          [anon:dalvik-allocspace non moving space live-bitmap 1]
-Name:           [anon:dalvik-allocspace non moving space live-bitmap 1]
-Size:               1004 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076e812000-70076e8f1000 r--p 00000000 fe:00 1114                       /system/lib64/libart-compiler.so
-Size:                892 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 188 kB
-Pss:                  27 kB
-Shared_Clean:        188 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          188 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               27 kB
-VmFlags: rd mr mw me 
-70076e8f1000-70076eb46000 r-xp 000df000 fe:00 1114                       /system/lib64/libart-compiler.so
-Size:               2388 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2092 kB
-Pss:                 201 kB
-Shared_Clean:       2092 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2092 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              201 kB
-VmFlags: rd ex mr mw me 
-70076eb46000-70076eb47000 rw-p 00334000 fe:00 1114                       /system/lib64/libart-compiler.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076eb47000-70076eb59000 r--p 00335000 fe:00 1114                       /system/lib64/libart-compiler.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         72 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:            72 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-70076eb59000-70076eb5a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076eb5b000-70076eb5d000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076eb5d000-70076eb5e000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076eb5e000-70076eb61000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076eb61000-70076eb62000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076eb62000-70076eb82000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                 124 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       124 kB
-Referenced:          124 kB
-Anonymous:           124 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              124 kB
-VmFlags: rd wr mr mw me ac 
-70076eb82000-70076eb9c000 r--p 00000000 fe:00 1229                       /system/lib64/libopenjdk.so
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 100 kB
-Pss:                   5 kB
-Shared_Clean:        100 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          100 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-70076eb9c000-70076ebb7000 r-xp 0001a000 fe:00 1229                       /system/lib64/libopenjdk.so
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 108 kB
-Pss:                   8 kB
-Shared_Clean:        108 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          108 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd ex mr mw me 
-70076ebb7000-70076ebb9000 rw-p 00035000 fe:00 1229                       /system/lib64/libopenjdk.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ebb9000-70076ebba000 r--p 00037000 fe:00 1229                       /system/lib64/libopenjdk.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-70076ebba000-70076ebbb000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076ebbb000-70076ebbd000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076ebbd000-70076ebbe000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076ebbe000-70076ebc1000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ebc1000-70076ebc2000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70076ebc2000-70076ebe2000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 112 kB
-Pss:                 112 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       112 kB
-Referenced:          112 kB
-Anonymous:           112 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              112 kB
-VmFlags: rd wr mr mw me ac 
-70076ebe2000-70076ebe6000 r--p 00000000 fe:00 1645                       /system/lib64/libopenjdkjvm.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   5 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-70076ebe6000-70076ebea000 r-xp 00004000 fe:00 1645                       /system/lib64/libopenjdkjvm.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-70076ebea000-70076ebeb000 rw-p 00008000 fe:00 1645                       /system/lib64/libopenjdkjvm.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ebeb000-70076ebec000 r--p 00009000 fe:00 1645                       /system/lib64/libopenjdkjvm.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-70076ebed000-70076ebef000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70076ebef000-70076ebf0000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076ebf0000-70076ebf8000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ebf8000-70076ebf9000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076ebf9000-70076ec01000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ec01000-70076ec02000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-70076ec02000-70076ec0a000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ec0a000-70076ec2a000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70076ec2a000-700770359000 r--s 00000000 fe:00 1096                       /system/usr/icu/icudt63l.dat
-Size:              23740 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1164 kB
-Pss:                 165 kB
-Shared_Clean:       1164 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         1164 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              165 kB
-VmFlags: rd mr me ms rr 
-700770359000-700770371000 r--p 00000000 fe:00 1615                       /system/lib64/libjavacore.so
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  92 kB
-Pss:                  10 kB
-Shared_Clean:         92 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           92 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-700770371000-700770396000 r-xp 00018000 fe:00 1615                       /system/lib64/libjavacore.so
-Size:                148 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 148 kB
-Pss:                   8 kB
-Shared_Clean:        148 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          148 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd ex mr mw me 
-700770396000-700770398000 rw-p 0003d000 fe:00 1615                       /system/lib64/libjavacore.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770398000-70077039a000 r--p 0003f000 fe:00 1615                       /system/lib64/libjavacore.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-70077039a000-70077039b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70077039c000-70077039e000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70077039e000-70077039f000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70077039f000-7007703a2000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703a2000-7007703a3000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007703a3000-7007703a4000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007703a4000-7007703ac000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703ac000-7007703cc000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703cc000-7007703ce000 r--p 00000000 fe:00 1134                       /system/lib64/libwebviewchromium_plat_support.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007703ce000-7007703cf000 r-xp 00002000 fe:00 1134                       /system/lib64/libwebviewchromium_plat_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007703cf000-7007703d0000 rw-p 00003000 fe:00 1134                       /system/lib64/libwebviewchromium_plat_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703d0000-7007703d1000 r--p 00004000 fe:00 1134                       /system/lib64/libwebviewchromium_plat_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007703d1000-7007703d2000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703d2000-7007703d3000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007703d3000-7007703d6000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703d6000-7007703d7000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007703d7000-7007703d8000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007703d8000-7007703e0000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007703e0000-700770400000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770400000-700770423000 r--p 00000000 fe:00 1228                       /system/lib64/android.hardware.renderscript@1.0.so
-Size:                140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  21 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-700770423000-70077047a000 r-xp 00023000 fe:00 1228                       /system/lib64/android.hardware.renderscript@1.0.so
-Size:                348 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-70077047a000-70077047b000 rw-p 0007a000 fe:00 1228                       /system/lib64/android.hardware.renderscript@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70077047b000-70077047f000 r--p 0007b000 fe:00 1228                       /system/lib64/android.hardware.renderscript@1.0.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770480000-700770481000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770481000-700770484000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770484000-700770486000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770486000-700770489000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770489000-70077048a000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70077048a000-7007704aa000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704aa000-7007704b2000 r--p 00000000 fe:00 1184                       /system/lib64/libRS.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  10 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007704b2000-7007704bc000 r-xp 00008000 fe:00 1184                       /system/lib64/libRS.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007704bc000-7007704bd000 rw-p 00012000 fe:00 1184                       /system/lib64/libRS.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704bd000-7007704be000 r--p 00013000 fe:00 1184                       /system/lib64/libRS.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007704be000-7007704bf000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704c0000-7007704c2000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007704c2000-7007704c3000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007704c3000-7007704c6000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704c6000-7007704c7000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007704c7000-7007704c8000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007704c8000-7007704d0000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704d0000-7007704d2000 r--p 00000000 fe:00 1768                       /system/lib64/libOpenSLES.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   2 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007704d2000-7007704d3000 r-xp 00002000 fe:00 1768                       /system/lib64/libOpenSLES.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007704d3000-7007704d4000 rw-p 00003000 fe:00 1768                       /system/lib64/libOpenSLES.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704d4000-7007704d5000 r--p 00004000 fe:00 1768                       /system/lib64/libOpenSLES.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007704d5000-7007704d6000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007704d6000-7007704d9000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704d9000-7007704da000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007704da000-7007704db000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007704db000-7007704e3000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007704e3000-700770503000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                 124 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       124 kB
-Referenced:          124 kB
-Anonymous:           124 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              124 kB
-VmFlags: rd wr mr mw me ac 
-700770503000-700770505000 r--p 00000000 fe:00 1250                       /system/lib64/libOpenMAXAL.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   2 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-700770505000-700770506000 r-xp 00002000 fe:00 1250                       /system/lib64/libOpenMAXAL.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770506000-700770507000 rw-p 00003000 fe:00 1250                       /system/lib64/libOpenMAXAL.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770507000-700770508000 r--p 00004000 fe:00 1250                       /system/lib64/libOpenMAXAL.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770508000-700770528000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770528000-700770551000 r--p 00000000 fe:00 1943                       /system/priv-app/SettingsProvider/SettingsProvider.apk
-Size:                164 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  88 kB
-Pss:                  88 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        88 kB
-Private_Dirty:         0 kB
-Referenced:           88 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               88 kB
-VmFlags: rd mr mw me ac 
-700770551000-700770575000 r--p 00000000 fe:00 1470                       /system/lib64/libneuralnetworks.so
-Size:                144 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  21 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-700770575000-70077065a000 r-xp 00024000 fe:00 1470                       /system/lib64/libneuralnetworks.so
-Size:                916 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-70077065a000-70077065b000 rw-p 00109000 fe:00 1470                       /system/lib64/libneuralnetworks.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70077065b000-70077065e000 r--p 0010a000 fe:00 1470                       /system/lib64/libneuralnetworks.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-70077065e000-70077096f000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:               3140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70077096f000-700770973000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700770973000-700770974000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770974000-700770977000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770977000-700770978000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770978000-700770979000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770979000-700770981000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770981000-70077098b000 r--s 00039000 fe:00 1943                       /system/priv-app/SettingsProvider/SettingsProvider.apk
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                  40 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:        40 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               40 kB
-VmFlags: rd mr me ms 
-70077098b000-7007709ab000 r--p 00000000 fe:00 1724                       /system/lib64/android.hardware.neuralnetworks@1.2.so
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  21 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-7007709ab000-7007709d1000 r-xp 00020000 fe:00 1724                       /system/lib64/android.hardware.neuralnetworks@1.2.so
-Size:                152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007709d1000-7007709d2000 rw-p 00046000 fe:00 1724                       /system/lib64/android.hardware.neuralnetworks@1.2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007709d2000-7007709d8000 r--p 00047000 fe:00 1724                       /system/lib64/android.hardware.neuralnetworks@1.2.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007709d8000-7007709da000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007709da000-7007709db000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007709db000-7007709de000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007709de000-7007709df000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007709df000-7007709e0000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007709e0000-7007709e8000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007709e8000-700770a08000 r--s 00000000 00:13 6735                       /dev/__properties__/u:object_r:serialno_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr me ms 
-700770a08000-700770a15000 r--p 00000000 fe:00 1214                       /system/lib64/android.hardware.neuralnetworks@1.1.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  17 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               17 kB
-VmFlags: rd mr mw me 
-700770a15000-700770a23000 r-xp 0000d000 fe:00 1214                       /system/lib64/android.hardware.neuralnetworks@1.1.so
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770a23000-700770a24000 rw-p 0001b000 fe:00 1214                       /system/lib64/android.hardware.neuralnetworks@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770a24000-700770a26000 r--p 0001c000 fe:00 1214                       /system/lib64/android.hardware.neuralnetworks@1.1.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770a26000-700770a2a000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700770a2a000-700770a2b000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770a2b000-700770a2e000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770a2e000-700770a2f000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770a2f000-700770a30000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770a30000-700770a38000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770a38000-700770a39000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770a39000-700770a3c000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770a3c000-700770a3d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770a3d000-700770a3e000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770a3e000-700770a46000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770a46000-700770a66000 r--s 00000000 00:13 6726                       /dev/__properties__/u:object_r:overlay_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700770a66000-700770a80000 r--p 00000000 fe:00 1136                       /system/lib64/android.hardware.neuralnetworks@1.0.so
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  21 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-700770a80000-700770aa1000 r-xp 0001a000 fe:00 1136                       /system/lib64/android.hardware.neuralnetworks@1.0.so
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770aa1000-700770aa2000 rw-p 0003b000 fe:00 1136                       /system/lib64/android.hardware.neuralnetworks@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770aa2000-700770aa7000 r--p 0003c000 fe:00 1136                       /system/lib64/android.hardware.neuralnetworks@1.0.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700770aa7000-700770aa9000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770aa9000-700770aaa000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770aaa000-700770ab2000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770ab2000-700770ab3000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770ab3000-700770abb000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770abb000-700770abc000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770abc000-700770ac4000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770ac4000-700770ac6000 r--p 00000000 fe:00 1183                       /system/lib64/libtextclassifier_hash.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700770ac6000-700770aca000 r-xp 00002000 fe:00 1183                       /system/lib64/libtextclassifier_hash.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770aca000-700770acb000 rw-p 00006000 fe:00 1183                       /system/lib64/libtextclassifier_hash.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770acb000-700770acc000 r--p 00007000 fe:00 1183                       /system/lib64/libtextclassifier_hash.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770acd000-700770b1f000 r--s 00000000 fe:00 211                        /system/fonts/Roboto-BoldItalic.ttf
-Size:                328 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700770b1f000-700770b20000 r--p 00000000 fe:00 1767                       /system/lib64/libjnigraphics.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700770b20000-700770b21000 r-xp 00001000 fe:00 1767                       /system/lib64/libjnigraphics.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770b21000-700770b22000 rw-p 00002000 fe:00 1767                       /system/lib64/libjnigraphics.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770b22000-700770b23000 r--p 00003000 fe:00 1767                       /system/lib64/libjnigraphics.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770b24000-700770b26000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770b26000-700770b27000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770b27000-700770b2a000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770b2a000-700770b2b000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770b2b000-700770b4b000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                  44 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        44 kB
-Referenced:           44 kB
-Anonymous:            44 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               44 kB
-VmFlags: rd wr mr mw me ac 
-700770b4b000-700770b4c000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770b4c000-700770b54000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770b54000-700770b67000 r--p 00000000 fe:00 1691                       /system/lib64/libGLESv3.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                  19 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               19 kB
-VmFlags: rd mr mw me 
-700770b67000-700770b6e000 r-xp 00013000 fe:00 1691                       /system/lib64/libGLESv3.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770b6e000-700770b6f000 rw-p 0001a000 fe:00 1691                       /system/lib64/libGLESv3.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770b6f000-700770b70000 r--p 0001b000 fe:00 1691                       /system/lib64/libGLESv3.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770b71000-700770b72000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700770b72000-700770b76000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770b76000-700770b77000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770b77000-700770b79000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-700770b79000-700770b7b000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770b7b000-700770b7c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770b7c000-700770b7f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770b7f000-700770b80000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770b80000-700770baa000 r--p 00000000 fe:00 1605                       /system/lib64/android.hardware.drm@1.0.so
-Size:                168 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700770baa000-700770bf8000 r-xp 0002a000 fe:00 1605                       /system/lib64/android.hardware.drm@1.0.so
-Size:                312 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770bf8000-700770bf9000 rw-p 00078000 fe:00 1605                       /system/lib64/android.hardware.drm@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770bf9000-700770c00000 r--p 00079000 fe:00 1605                       /system/lib64/android.hardware.drm@1.0.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         28 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700770c00000-700770c01000 rw-s 00000000 00:05 19682                      /dev/ashmem/GFXStats-2254 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr sh mr mw me ms 
-700770c01000-700770c02000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c02000-700770c05000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c05000-700770c06000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c06000-700770c15000 r--p 00000000 fe:00 1658                       /system/lib64/libcamera2ndk.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                  19 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               19 kB
-VmFlags: rd mr mw me 
-700770c15000-700770c28000 r-xp 0000f000 fe:00 1658                       /system/lib64/libcamera2ndk.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770c28000-700770c29000 rw-p 00022000 fe:00 1658                       /system/lib64/libcamera2ndk.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c29000-700770c2b000 r--p 00023000 fe:00 1658                       /system/lib64/libcamera2ndk.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770c2b000-700770c2c000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c2c000-700770c2d000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700770c2d000-700770c2f000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770c2f000-700770c30000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c30000-700770c33000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c33000-700770c35000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c35000-700770c38000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c38000-700770c39000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c39000-700770c3a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770c3a000-700770c42000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c42000-700770c43000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c43000-700770c46000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c46000-700770c47000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c47000-700770c48000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770c48000-700770c50000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c50000-700770c51000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c51000-700770c54000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c54000-700770c55000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770c55000-700770c67000 r--p 00000000 fe:00 1269                       /system/lib64/libmediadrmmetrics_lite.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700770c67000-700770c79000 r-xp 00012000 fe:00 1269                       /system/lib64/libmediadrmmetrics_lite.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770c79000-700770c7a000 rw-p 00024000 fe:00 1269                       /system/lib64/libmediadrmmetrics_lite.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c7a000-700770c7c000 r--p 00025000 fe:00 1269                       /system/lib64/libmediadrmmetrics_lite.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770c7c000-700770c7d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c7d000-700770c7f000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770c7f000-700770c80000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770c80000-700770c88000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770c88000-700770c9c000 r--p 00000000 fe:00 1173                       /system/lib64/libexif.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                  15 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               15 kB
-VmFlags: rd mr mw me 
-700770c9c000-700770cac000 r-xp 00014000 fe:00 1173                       /system/lib64/libexif.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770cac000-700770cad000 rw-p 00024000 fe:00 1173                       /system/lib64/libexif.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770cad000-700770cc0000 r--p 00025000 fe:00 1173                       /system/lib64/libexif.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  76 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         76 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            76 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700770cc0000-700770cc2000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770cc2000-700770cd8000 r--p 00000000 fe:00 1584                       /system/lib64/libmtp.so
-Size:                 88 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700770cd8000-700770cf0000 r-xp 00016000 fe:00 1584                       /system/lib64/libmtp.so
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  88 kB
-Pss:                  58 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:        28 kB
-Private_Dirty:         0 kB
-Referenced:           88 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               58 kB
-VmFlags: rd ex mr mw me 
-700770cf0000-700770cf1000 rw-p 0002e000 fe:00 1584                       /system/lib64/libmtp.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770cf1000-700770cf4000 r--p 0002f000 fe:00 1584                       /system/lib64/libmtp.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770cf4000-700770cf5000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770cf5000-700770cf9000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770cf9000-700770cfa000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770cfa000-700770cfd000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770cfd000-700770cfe000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770cfe000-700770cff000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770cff000-700770d07000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770d07000-700770d08000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770d08000-700770d10000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770d10000-700770d11000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700770d11000-700770d13000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770d13000-700770d14000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770d14000-700770d17000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770d17000-700770d18000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770d18000-700770d38000 r--s 00000000 00:13 6730                       /dev/__properties__/u:object_r:pm_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms 
-700770d38000-700770d39000 r--p 00000000 fe:00 1731                       /system/lib64/libasyncio.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-700770d39000-700770d3a000 r-xp 00001000 fe:00 1731                       /system/lib64/libasyncio.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770d3a000-700770d3b000 rw-p 00002000 fe:00 1731                       /system/lib64/libasyncio.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770d3b000-700770d3c000 r--p 00003000 fe:00 1731                       /system/lib64/libasyncio.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770d3d000-700770d3f000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770d3f000-700770d40000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770d40000-700770d43000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770d43000-700770d44000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770d44000-700770d77000 r--p 00000000 fe:00 1573                       /system/lib64/libmedia_jni.so
-Size:                204 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  15 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               15 kB
-VmFlags: rd mr mw me 
-700770d77000-700770dae000 r-xp 00033000 fe:00 1573                       /system/lib64/libmedia_jni.so
-Size:                220 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770dae000-700770daf000 rw-p 0006a000 fe:00 1573                       /system/lib64/libmedia_jni.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770daf000-700770db5000 r--p 0006b000 fe:00 1573                       /system/lib64/libmedia_jni.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700770db5000-700770db6000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770db6000-700770db7000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770db7000-700770dbf000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770dbf000-700770dc0000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770dc0000-700770dc3000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770dc3000-700770dc4000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770dc4000-700770dc5000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770dc5000-700770dcd000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770dcd000-700770dce000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770dce000-700770dd1000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770dd1000-700770dd2000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770dd2000-700770dd3000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770dd3000-700770ddb000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770ddb000-700770ddc000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770ddc000-700770de4000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770de4000-700770ded000 r--p 00000000 fe:00 1558                       /system/lib64/libmidi.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   9 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-700770ded000-700770df7000 r-xp 00009000 fe:00 1558                       /system/lib64/libmidi.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770df7000-700770df8000 rw-p 00013000 fe:00 1558                       /system/lib64/libmidi.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770df8000-700770dfa000 r--p 00014000 fe:00 1558                       /system/lib64/libmidi.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770dfa000-700770dfb000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770dfb000-700770dfc000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770dfc000-700770dff000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770dff000-700770e00000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770e00000-700770e1a000 r--p 00000000 fe:00 1744                       /system/lib64/libmediadrm.so
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700770e1a000-700770e32000 r-xp 0001a000 fe:00 1744                       /system/lib64/libmediadrm.so
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770e32000-700770e33000 rw-p 00032000 fe:00 1744                       /system/lib64/libmediadrm.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e33000-700770e3a000 r--p 00033000 fe:00 1744                       /system/lib64/libmediadrm.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         28 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700770e3a000-700770e3b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e3b000-700770e3c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770e3c000-700770e3f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e3f000-700770e40000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770e40000-700770e41000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770e41000-700770e49000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e49000-700770e59000 r--p 00000000 fe:00 1239                       /system/lib64/libmediandk.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  14 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               14 kB
-VmFlags: rd mr mw me 
-700770e59000-700770e66000 r-xp 00010000 fe:00 1239                       /system/lib64/libmediandk.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  26 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               26 kB
-VmFlags: rd ex mr mw me 
-700770e66000-700770e67000 rw-p 0001d000 fe:00 1239                       /system/lib64/libmediandk.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e67000-700770e69000 r--p 0001e000 fe:00 1239                       /system/lib64/libmediandk.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770e69000-700770e6a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e6a000-700770e6e000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700770e6e000-700770e6f000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770e6f000-700770e77000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770e77000-700770e97000 r--s 00000000 00:13 6713                       /dev/__properties__/u:object_r:hwservicemanager_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700770e97000-700770eb7000 r--p 00000000 fe:00 1647                       /system/lib64/android.hardware.drm@1.1.so
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-700770eb7000-700770ee3000 r-xp 00020000 fe:00 1647                       /system/lib64/android.hardware.drm@1.1.so
-Size:                176 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770ee3000-700770ee4000 rw-p 0004c000 fe:00 1647                       /system/lib64/android.hardware.drm@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770ee4000-700770eea000 r--p 0004d000 fe:00 1647                       /system/lib64/android.hardware.drm@1.1.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700770eea000-700770eeb000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700770eeb000-700770eed000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770eed000-700770eee000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770eee000-700770ef1000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770ef1000-700770ef2000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770ef2000-700770ef3000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770ef3000-700770efb000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770efb000-700770f1b000 r--s 00000000 00:13 6745                       /dev/__properties__/u:object_r:vendor_default_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700770f1b000-700770f22000 r--p 00000000 fe:00 1701                       /system/lib64/libbinder_ndk.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   9 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-700770f22000-700770f28000 r-xp 00007000 fe:00 1701                       /system/lib64/libbinder_ndk.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770f28000-700770f29000 rw-p 0000d000 fe:00 1701                       /system/lib64/libbinder_ndk.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f29000-700770f2a000 r--p 0000e000 fe:00 1701                       /system/lib64/libbinder_ndk.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770f2a000-700770f2b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f2b000-700770f2c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770f2c000-700770f2f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f2f000-700770f31000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770f31000-700770f34000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f34000-700770f35000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770f35000-700770f36000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770f36000-700770f3e000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f3e000-700770f3f000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770f3f000-700770f47000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f47000-700770f62000 r--p 00000000 fe:00 1703                       /system/lib64/libaaudio.so
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  21 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-700770f62000-700770f74000 r-xp 0001b000 fe:00 1703                       /system/lib64/libaaudio.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770f74000-700770f75000 rw-p 0002d000 fe:00 1703                       /system/lib64/libaaudio.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f75000-700770f7a000 r--p 0002e000 fe:00 1703                       /system/lib64/libaaudio.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-700770f7a000-700770f7b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770f7b000-700770f7c000 rw-s 00000000 00:05 11676                      /dev/ashmem/GFXStats-1674 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr sh mr mw me ms 
-700770f7c000-700770fa0000 r--s 00000000 fe:00 985                        /system/usr/hyphen-data/hyph-nn.hyb
-Size:                144 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700770fa0000-700770faf000 r--p 00000000 fe:00 1602                       /system/lib64/libandroid.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                  15 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               15 kB
-VmFlags: rd mr mw me 
-700770faf000-700770fb8000 r-xp 0000f000 fe:00 1602                       /system/lib64/libandroid.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700770fb8000-700770fb9000 rw-p 00018000 fe:00 1602                       /system/lib64/libandroid.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770fb9000-700770fbb000 r--p 00019000 fe:00 1602                       /system/lib64/libandroid.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770fbb000-700770fbc000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770fbc000-700770fc0000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700770fc0000-700770fc1000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700770fc1000-700770fc9000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770fc9000-700770fce000 r--p 00000000 fe:00 1736                       /system/lib64/libadbconnection.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700770fce000-700770fd6000 r-xp 00005000 fe:00 1736                       /system/lib64/libadbconnection.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   1 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-700770fd6000-700770fd7000 rw-p 0000d000 fe:00 1736                       /system/lib64/libadbconnection.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770fd7000-700770fd8000 r--p 0000e000 fe:00 1736                       /system/lib64/libadbconnection.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700770fd8000-700770fd9000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770fd9000-700770fda000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770fda000-700770fdd000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700770fdd000-700770fde000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700770fde000-70077102f000 r--s 00000000 fe:00 231                        /system/fonts/Roboto-BlackItalic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-70077102f000-7007711bf000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:               1600 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           24 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me ac 
-7007711bf000-7007712bf000 rw-p 00000000 00:00 0                          [anon:dalvik-non-moving-space inter region ref bitmap]
-Name:           [anon:dalvik-non-moving-space inter region ref bitmap]
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007712bf000-7007722bf000 rw-p 00000000 00:00 0                          [anon:dalvik-region-space inter region ref bitmap]
-Name:           [anon:dalvik-region-space inter region ref bitmap]
-Size:              16384 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007722bf000-7007724bf000 rw-p 00000000 00:00 0                          [anon:dalvik-rb copying gc mark stack]
-Name:           [anon:dalvik-rb copying gc mark stack]
-Size:               2048 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007724bf000-700772cbf000 rw-p 00000000 00:00 0                          [anon:dalvik-concurrent copying gc mark stack]
-Name:           [anon:dalvik-concurrent copying gc mark stack]
-Size:               8192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700772cbf000-700772ebf000 rw-p 00000000 00:00 0                          [anon:dalvik-rb copying gc mark stack]
-Name:           [anon:dalvik-rb copying gc mark stack]
-Size:               2048 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700772ebf000-7007736bf000 rw-p 00000000 00:00 0                          [anon:dalvik-concurrent copying gc mark stack]
-Name:           [anon:dalvik-concurrent copying gc mark stack]
-Size:               8192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007736bf000-700773ec0000 rw-p 00000000 00:00 0                          [anon:dalvik-live stack]
-Name:           [anon:dalvik-live stack]
-Size:               8196 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700773ec0000-7007746c1000 rw-p 00000000 00:00 0                          [anon:dalvik-allocation stack]
-Name:           [anon:dalvik-allocation stack]
-Size:               8196 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007746c1000-700774ac2000 rw-p 00000000 00:00 0                          [anon:dalvik-card table]
-Name:           [anon:dalvik-card table]
-Size:               4100 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  56 kB
-Pss:                  56 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        56 kB
-Referenced:           56 kB
-Anonymous:            56 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               56 kB
-VmFlags: rd wr mr mw me ac 
-700774ac2000-700775ac2000 rw-p 00000000 00:00 0                          [anon:dalvik-region space live bitmap]
-Name:           [anon:dalvik-region space live bitmap]
-Size:              16384 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  84 kB
-Pss:                  84 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        84 kB
-Referenced:           84 kB
-Anonymous:            84 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               84 kB
-VmFlags: rd wr mr mw me ac 
-700775ac2000-700775bc2000 rw-p 00000000 00:00 0                          [anon:dalvik-allocspace zygote / non moving space mark-bitmap 0]
-Name:           [anon:dalvik-allocspace zygote / non moving space mark-bitmap 0]
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700775bc2000-700775cc2000 rw-p 00000000 00:00 0                          [anon:dalvik-allocspace zygote / non moving space live-bitmap 0]
-Name:           [anon:dalvik-allocspace zygote / non moving space live-bitmap 0]
-Size:               1024 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd wr mr mw me ac 
-700775cc2000-700775cc4000 r--p 00000000 fe:00 1730                       /system/lib64/libsigchain.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700775cc4000-700775cc6000 r-xp 00002000 fe:00 1730                       /system/lib64/libsigchain.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700775cc6000-700775cc7000 rw-p 00004000 fe:00 1730                       /system/lib64/libsigchain.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700775cc7000-700775cc8000 r--p 00005000 fe:00 1730                       /system/lib64/libsigchain.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700775cc8000-700775ccc000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700775ccc000-700775ccd000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700775ccd000-700775cd5000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700775cd5000-700775d26000 r--s 00000000 fe:00 219                        /system/fonts/Roboto-MediumItalic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700775d26000-700775d27000 r--p 00000000 fe:00 1509                       /system/lib64/libstatssocket.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700775d27000-700775d28000 r-xp 00001000 fe:00 1509                       /system/lib64/libstatssocket.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700775d28000-700775d29000 rw-p 00002000 fe:00 1509                       /system/lib64/libstatssocket.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700775d29000-700775d2a000 r--p 00003000 fe:00 1509                       /system/lib64/libstatssocket.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700775d2a000-700775d2b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700775d2b000-700775d2f000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700775d2f000-700775d7a000 r--s 00000000 fe:00 275                        /system/fonts/Roboto-Bold.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700775d7a000-700775ece000 r--p 00000000 fe:00 1156                       /system/lib64/libart.so
-Size:               1360 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 384 kB
-Pss:                  39 kB
-Shared_Clean:        384 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          384 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               39 kB
-VmFlags: rd mr mw me 
-700775ece000-7007763e6000 r-xp 00154000 fe:00 1156                       /system/lib64/libart.so
-Size:               5216 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                4276 kB
-Pss:                 288 kB
-Shared_Clean:       4272 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:         4276 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              288 kB
-VmFlags: rd ex mr mw me 
-7007763e6000-7007763e9000 rw-p 0066c000 fe:00 1156                       /system/lib64/libart.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            8 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007763e9000-7007763f9000 r--p 0066f000 fe:00 1156                       /system/lib64/libart.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         64 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           56 kB
-Anonymous:            64 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-7007763f9000-7007763fc000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd wr mr mw me ac 
-7007763fc000-700776400000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700776400000-700776800000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:               4096 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                4080 kB
-Pss:                3230 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        900 kB
-Private_Clean:         0 kB
-Private_Dirty:      3180 kB
-Referenced:         3992 kB
-Anonymous:          4080 kB
-AnonHugePages:      2048 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             3230 kB
-VmFlags: rd wr mr mw me ac 
-700776800000-700776804000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-700776804000-700776805000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-700776805000-700776807000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700776807000-700776808000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-700776808000-700776810000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700776810000-700776861000 r--s 00000000 fe:00 195                        /system/fonts/Roboto-Italic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700776861000-700776862000 r--p 00000000 fe:00 1199                       /system/lib64/libmetricslogger.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-700776862000-700776863000 r-xp 00001000 fe:00 1199                       /system/lib64/libmetricslogger.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700776863000-700776864000 rw-p 00002000 fe:00 1199                       /system/lib64/libmetricslogger.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700776864000-700776865000 r--p 00003000 fe:00 1199                       /system/lib64/libmetricslogger.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700776865000-700776866000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700776866000-700776867000 r--s 00009000 fe:00 2036                       /system/priv-app/FusedLocation/FusedLocation.apk
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr me ms 
-700776867000-700776868000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700776868000-70077686b000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-70077686b000-70077686c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70077686c000-700776890000 r--s 00000000 fe:00 1019                       /system/usr/hyphen-data/hyph-nb.hyb
-Size:                144 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-700776890000-700776892000 r--p 00000000 fe:00 1606                       /system/lib64/libtombstoned_client.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   2 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-700776892000-700776895000 r-xp 00002000 fe:00 1606                       /system/lib64/libtombstoned_client.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-700776895000-700776896000 rw-p 00005000 fe:00 1606                       /system/lib64/libtombstoned_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700776896000-700776897000 r--p 00006000 fe:00 1606                       /system/lib64/libtombstoned_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-700776897000-700776899000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-700776899000-70077689a000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70077689a000-70077689d000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-70077689d000-70077689f000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-70077689f000-7007768a2000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007768a2000-7007768a3000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007768a3000-7007768c1000 r--s 00000000 fe:00 971                        /system/usr/hyphen-data/hyph-de-ch-1901.hyb
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007768c1000-7007768d2000 r--p 00000000 fe:00 1651                       /system/lib64/libprofile.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007768d2000-7007768f3000 r-xp 00011000 fe:00 1651                       /system/lib64/libprofile.so
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007768f3000-7007768f4000 rw-p 00032000 fe:00 1651                       /system/lib64/libprofile.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007768f4000-7007768f5000 r--p 00033000 fe:00 1651                       /system/lib64/libprofile.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007768f5000-7007768f6000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007768f6000-7007768f8000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007768f8000-7007768f9000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007768f9000-700776901000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700776901000-700776902000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700776902000-700776905000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-700776905000-700776906000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-700776906000-700776909000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me nr 
-700776909000-70077690a000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-70077690a000-7007a2575000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:             717228 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me nr 
-7007a2575000-7007a2576000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007a2576000-7007ae940000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:             200488 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me nr 
-7007ae940000-7007ae941000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007ae941000-7007ae942000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007ae942000-7007ae945000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me nr 
-7007ae945000-7007ae946000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007ae946000-7007b68f5000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:             130748 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me nr 
-7007b68f5000-7007b68f6000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007b68f6000-7007f6906000 r--p 00000000 00:00 0                          [anon:cfi shadow]
-Name:           [anon:cfi shadow]
-Size:            1048640 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me nr 
-7007f6906000-7007f690d000 r--p 00000000 fe:00 1707                       /system/lib64/libmediautils.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   4 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007f690d000-7007f6912000 r-xp 00007000 fe:00 1707                       /system/lib64/libmediautils.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6912000-7007f6913000 rw-p 0000c000 fe:00 1707                       /system/lib64/libmediautils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6913000-7007f6915000 r--p 0000d000 fe:00 1707                       /system/lib64/libmediautils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6915000-7007f6916000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6916000-7007f6917000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6917000-7007f6919000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6919000-7007f691a000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f691a000-7007f6922000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6922000-7007f6940000 r--s 00000000 fe:00 976                        /system/usr/hyphen-data/hyph-de-1996.hyb
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6940000-7007f694d000 r--p 00000000 fe:00 1526                       /system/lib64/libmedia_helper.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                   8 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-7007f694d000-7007f6955000 r-xp 0000d000 fe:00 1526                       /system/lib64/libmedia_helper.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6955000-7007f6956000 rw-p 00015000 fe:00 1526                       /system/lib64/libmedia_helper.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6956000-7007f6958000 r--p 00016000 fe:00 1526                       /system/lib64/libmedia_helper.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6958000-7007f6959000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6959000-7007f695a000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f695a000-7007f695c000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f695c000-7007f695d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f695d000-7007f6960000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6960000-7007f6961000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6961000-7007f6963000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6963000-7007f6964000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6964000-7007f696c000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f696c000-7007f696d000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f696d000-7007f6970000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007f6970000-7007f6971000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6971000-7007f698f000 r--s 00000000 fe:00 991                        /system/usr/hyphen-data/hyph-de-1901.hyb
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f698f000-7007f699d000 r--p 00000000 fe:00 1227                       /system/lib64/libminikin.so
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                   8 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-7007f699d000-7007f69b5000 r-xp 0000e000 fe:00 1227                       /system/lib64/libminikin.so
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  96 kB
-Pss:                  24 kB
-Shared_Clean:         96 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           96 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd ex mr mw me 
-7007f69b5000-7007f69b6000 rw-p 00026000 fe:00 1227                       /system/lib64/libminikin.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69b6000-7007f69b7000 r--p 00027000 fe:00 1227                       /system/lib64/libminikin.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f69b7000-7007f69b8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f69b8000-7007f69ba000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f69ba000-7007f69c1000 rw-p 00000000 fe:00 944                        /system/etc/event-log-tags
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   2 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr mr mw me ac 
-7007f69c1000-7007f69c2000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f69c2000-7007f69ca000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69ca000-7007f69d4000 r--p 00000000 fe:00 1135                       /system/lib64/android.hidl.memory.token@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   7 kB
-Shared_Clean:         40 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007f69d4000-7007f69dd000 r-xp 0000a000 fe:00 1135                       /system/lib64/android.hidl.memory.token@1.0.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f69dd000-7007f69de000 rw-p 00013000 fe:00 1135                       /system/lib64/android.hidl.memory.token@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69de000-7007f69e0000 r--p 00014000 fe:00 1135                       /system/lib64/android.hidl.memory.token@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f69e0000-7007f69e1000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f69e1000-7007f69e4000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69e4000-7007f69e6000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f69e6000-7007f69e9000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69e9000-7007f69ea000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f69ea000-7007f69eb000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f69eb000-7007f69f3000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69f3000-7007f69f4000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f69f4000-7007f69fc000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f69fc000-7007f6a1c000 r--s 00000000 00:13 6716                       /dev/__properties__/u:object_r:log_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6a1c000-7007f6a1d000 r--p 00000000 fe:00 1746                       /system/lib64/android.hardware.configstore-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f6a1d000-7007f6a1e000 r-xp 00001000 fe:00 1746                       /system/lib64/android.hardware.configstore-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-7007f6a1e000-7007f6a1f000 rw-p 00002000 fe:00 1746                       /system/lib64/android.hardware.configstore-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6a1f000-7007f6a20000 r--p 00003000 fe:00 1746                       /system/lib64/android.hardware.configstore-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6a20000-7007f6a21000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6a21000-7007f6a24000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6a24000-7007f6a25000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6a25000-7007f6a45000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6a45000-7007f6a56000 r--p 00000000 fe:00 1599                       /system/lib64/libvulkan.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  12 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-7007f6a56000-7007f6a69000 r-xp 00011000 fe:00 1599                       /system/lib64/libvulkan.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6a69000-7007f6a6a000 rw-p 00024000 fe:00 1599                       /system/lib64/libvulkan.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6a6a000-7007f6a6c000 r--p 00025000 fe:00 1599                       /system/lib64/libvulkan.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6a6c000-7007f6a6d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6a6d000-7007f6a8d000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6a8d000-7007f6ab4000 r--p 00000000 fe:00 1727                       /system/lib64/libandroidicu.so
-Size:                156 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  16 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd mr mw me 
-7007f6ab4000-7007f6abc000 r-xp 00027000 fe:00 1727                       /system/lib64/libandroidicu.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6abc000-7007f6abd000 rw-p 0002f000 fe:00 1727                       /system/lib64/libandroidicu.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6abd000-7007f6abf000 r--p 00030000 fe:00 1727                       /system/lib64/libandroidicu.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6abf000-7007f6ac3000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ac3000-7007f6ac4000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6ac4000-7007f6acc000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6acc000-7007f6acd000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6acd000-7007f6ad0000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ad0000-7007f6ad1000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6ad1000-7007f6ad2000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6ad2000-7007f6ada000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ada000-7007f6ae9000 r--p 00000000 fe:00 1717                       /system/lib64/android.hardware.configstore@1.1.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   5 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f6ae9000-7007f6af7000 r-xp 0000f000 fe:00 1717                       /system/lib64/android.hardware.configstore@1.1.so
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6af7000-7007f6af8000 rw-p 0001d000 fe:00 1717                       /system/lib64/android.hardware.configstore@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6af8000-7007f6afb000 r--p 0001e000 fe:00 1717                       /system/lib64/android.hardware.configstore@1.1.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6afb000-7007f6afc000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f6afc000-7007f6afe000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6afe000-7007f6aff000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6aff000-7007f6b02000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6b02000-7007f6b04000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6b04000-7007f6b07000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6b07000-7007f6b08000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6b08000-7007f6b09000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6b09000-7007f6b11000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6b11000-7007f6b62000 r--p 00000000 fe:00 1580                       /system/lib64/libbinder.so
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 252 kB
-Pss:                   9 kB
-Shared_Clean:        252 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          252 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f6b62000-7007f6ba1000 r-xp 00051000 fe:00 1580                       /system/lib64/libbinder.so
-Size:                252 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 248 kB
-Pss:                   6 kB
-Shared_Clean:        248 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          248 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-7007f6ba1000-7007f6ba2000 rw-p 00090000 fe:00 1580                       /system/lib64/libbinder.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ba2000-7007f6bb1000 r--p 00091000 fe:00 1580                       /system/lib64/libbinder.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         60 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:            60 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-7007f6bb1000-7007f6bb2000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6bb2000-7007f6bb3000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6bb3000-7007f6bb6000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6bb6000-7007f6bb7000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6bb7000-7007f6bb8000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6bb8000-7007f6bc0000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6bc0000-7007f6bc1000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6bc1000-7007f6bc9000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6bc9000-7007f6bdf000 r--p 00000000 fe:00 1694                       /system/lib64/libinput.so
-Size:                 88 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  88 kB
-Pss:                  20 kB
-Shared_Clean:         88 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           88 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me 
-7007f6bdf000-7007f6bf3000 r-xp 00016000 fe:00 1694                       /system/lib64/libinput.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                  18 kB
-Shared_Clean:         72 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           72 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               18 kB
-VmFlags: rd ex mr mw me 
-7007f6bf3000-7007f6bf4000 rw-p 0002a000 fe:00 1694                       /system/lib64/libinput.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6bf4000-7007f6bfb000 r--p 0002b000 fe:00 1694                       /system/lib64/libinput.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         28 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f6bfb000-7007f6bfc000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6bfc000-7007f6bfd000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007f6bfd000-7007f6c05000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6c05000-7007f6c0e000 r--s 00000000 fe:00 972                        /system/usr/hyphen-data/hyph-ga.hyb
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6c0e000-7007f6c1a000 r--p 00000000 fe:00 1613                       /system/lib64/android.hardware.graphics.mapper@2.0.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   4 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007f6c1a000-7007f6c26000 r-xp 0000c000 fe:00 1613                       /system/lib64/android.hardware.graphics.mapper@2.0.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   6 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-7007f6c26000-7007f6c27000 rw-p 00018000 fe:00 1613                       /system/lib64/android.hardware.graphics.mapper@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6c27000-7007f6c29000 r--p 00019000 fe:00 1613                       /system/lib64/android.hardware.graphics.mapper@2.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6c29000-7007f6c2b000 r--p 0007b000 fe:00 3288                       /system/framework/oat/x86_64/services.art
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-7007f6c2b000-7007f6c3a000 r--s 00000000 fe:00 984                        /system/usr/hyphen-data/hyph-en-us.hyb
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                  30 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               30 kB
-VmFlags: rd mr me ms 
-7007f6c3a000-7007f6c46000 r--s 00000000 fe:00 1020                       /system/usr/hyphen-data/hyph-en-gb.hyb
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6c46000-7007f6c5b000 r--p 00000000 fe:00 1210                       /system/lib64/libstagefright_foundation.so
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  10 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007f6c5b000-7007f6c7a000 r-xp 00015000 fe:00 1210                       /system/lib64/libstagefright_foundation.so
-Size:                124 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                  27 kB
-Shared_Clean:        124 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          124 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               27 kB
-VmFlags: rd ex mr mw me 
-7007f6c7a000-7007f6c7b000 rw-p 00034000 fe:00 1210                       /system/lib64/libstagefright_foundation.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6c7b000-7007f6c7d000 r--p 00035000 fe:00 1210                       /system/lib64/libstagefright_foundation.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6c7d000-7007f6c7e000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6c7e000-7007f6c7f000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f6c7f000-7007f6c81000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6c81000-7007f6ca1000 rw-p 00000000 00:00 0                          [anon:dalvik-CompilerMetadata]
-Name:           [anon:dalvik-CompilerMetadata]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ca1000-7007f6ca3000 r--p 00000000 fe:00 1711                       /system/lib64/libhardware_legacy.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   1 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f6ca3000-7007f6ca5000 r-xp 00002000 fe:00 1711                       /system/lib64/libhardware_legacy.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd ex mr mw me 
-7007f6ca5000-7007f6ca6000 rw-p 00004000 fe:00 1711                       /system/lib64/libhardware_legacy.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ca6000-7007f6ca7000 r--p 00005000 fe:00 1711                       /system/lib64/libhardware_legacy.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6ca7000-7007f6ca8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ca8000-7007f6ca9000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6ca9000-7007f6cac000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6cac000-7007f6cad000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007f6cad000-7007f6cba000 r--s 00000000 fe:00 1022                       /system/usr/hyphen-data/hyph-cu.hyb
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6cba000-7007f6cda000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                 128 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:       128 kB
-Referenced:          128 kB
-Anonymous:           128 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              128 kB
-VmFlags: rd wr mr mw me ac 
-7007f6cda000-7007f6cdf000 r--p 00000000 fe:00 1678                       /system/lib64/libappfuse.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   5 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f6cdf000-7007f6ce6000 r-xp 00005000 fe:00 1678                       /system/lib64/libappfuse.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6ce6000-7007f6ce7000 rw-p 0000c000 fe:00 1678                       /system/lib64/libappfuse.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ce7000-7007f6ce8000 r--p 0000d000 fe:00 1678                       /system/lib64/libappfuse.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6ce8000-7007f6cea000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6cea000-7007f6cf3000 r--s 00000000 fe:00 1000                       /system/usr/hyphen-data/hyph-cy.hyb
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6cf3000-7007f6d0c000 r--s 00000000 fe:00 162                        /system/fonts/NotoSansBhaiksuki-Regular.otf
-Size:                100 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6d0c000-7007f6d18000 r--p 00000000 fe:00 1607                       /system/lib64/android.hardware.cas.native@1.0.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   9 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f6d18000-7007f6d23000 r-xp 0000c000 fe:00 1607                       /system/lib64/android.hardware.cas.native@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6d23000-7007f6d24000 rw-p 00017000 fe:00 1607                       /system/lib64/android.hardware.cas.native@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6d24000-7007f6d26000 r--p 00018000 fe:00 1607                       /system/lib64/android.hardware.cas.native@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6d26000-7007f6d2c000 r--s 00000000 fe:00 1025                       /system/usr/hyphen-data/hyph-et.hyb
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6d2c000-7007f6d3d000 r--s 00000000 fe:00 274                        /system/fonts/NotoSansNewa-Regular.otf
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6d3d000-7007f6d5e000 r--s 00000000 fe:00 142                        /system/fonts/NotoSansAnatolianHieroglyphs-Regular.otf
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6d5e000-7007f6d60000 r--p 00000000 fe:00 1650                       /system/lib64/libstagefright_omx_utils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   1 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f6d60000-7007f6d62000 r-xp 00002000 fe:00 1650                       /system/lib64/libstagefright_omx_utils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   4 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me 
-7007f6d62000-7007f6d63000 rw-p 00004000 fe:00 1650                       /system/lib64/libstagefright_omx_utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6d63000-7007f6d64000 r--p 00005000 fe:00 1650                       /system/lib64/libstagefright_omx_utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6d64000-7007f6d65000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6d65000-7007f6d67000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6d67000-7007f6db2000 r--s 00000000 fe:00 144                        /system/fonts/Roboto-Black.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6db2000-7007f6db5000 r--p 00000000 fe:00 1142                       /system/lib64/libhidlmemory.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   2 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007f6db5000-7007f6db7000 r-xp 00003000 fe:00 1142                       /system/lib64/libhidlmemory.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   2 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-7007f6db7000-7007f6db8000 rw-p 00005000 fe:00 1142                       /system/lib64/libhidlmemory.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6db8000-7007f6db9000 r--p 00006000 fe:00 1142                       /system/lib64/libhidlmemory.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6db9000-7007f6dba000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6dba000-7007f6dca000 r--s 00000000 fe:00 119                        /system/fonts/NotoSansMarchen-Regular.otf
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6dca000-7007f6dcc000 r--p 00000000 fe:00 1469                       /system/lib64/libprocessgroup.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f6dcc000-7007f6dcf000 r-xp 00002000 fe:00 1469                       /system/lib64/libprocessgroup.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6dcf000-7007f6dd0000 rw-p 00005000 fe:00 1469                       /system/lib64/libprocessgroup.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6dd0000-7007f6dd1000 r--p 00006000 fe:00 1469                       /system/lib64/libprocessgroup.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6dd1000-7007f6dd2000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6dd2000-7007f6dd3000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f6dd3000-7007f6dd7000 r--s 00000000 fe:00 1008                       /system/usr/hyphen-data/hyph-es.hyb
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6dd7000-7007f6dde000 r--s 00000000 fe:00 132                        /system/fonts/NotoSansSharada-Regular.otf
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6dde000-7007f6de7000 r--s 00000000 fe:00 157                        /system/fonts/NotoSansLinearA-Regular.otf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6de7000-7007f6e03000 r--s 00000000 fe:00 139                        /system/fonts/NotoSansMongolian-Regular.ttf
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6e03000-7007f6e15000 r--p 00000000 fe:00 1511                       /system/lib64/libpdx_default_transport.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   9 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f6e15000-7007f6e29000 r-xp 00012000 fe:00 1511                       /system/lib64/libpdx_default_transport.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6e29000-7007f6e2a000 rw-p 00026000 fe:00 1511                       /system/lib64/libpdx_default_transport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6e2a000-7007f6e2b000 r--p 00027000 fe:00 1511                       /system/lib64/libpdx_default_transport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6e2b000-7007f6e2c000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6e2c000-7007f6e2d000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f6e2d000-7007f6e2f000 r--s 00000000 fe:00 964                        /system/usr/hyphen-data/hyph-sl.hyb
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6e2f000-7007f6e4e000 r--s 00000000 fe:00 289                        /system/fonts/NotoSansYi-Regular.ttf
-Size:                124 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6e4e000-7007f6e60000 r--p 00000000 fe:00 1545                       /system/lib64/libEGL.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  72 kB
-Pss:                   8 kB
-Shared_Clean:         72 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           72 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-7007f6e60000-7007f6e73000 r-xp 00012000 fe:00 1545                       /system/lib64/libEGL.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  76 kB
-Pss:                   3 kB
-Shared_Clean:         76 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           76 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd ex mr mw me 
-7007f6e73000-7007f6e74000 rw-p 00025000 fe:00 1545                       /system/lib64/libEGL.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6e74000-7007f6e78000 r--p 00026000 fe:00 1545                       /system/lib64/libEGL.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6e78000-7007f6e80000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           20 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me ac 
-7007f6e80000-7007f6e82000 r--s 00000000 fe:00 983                        /system/usr/hyphen-data/hyph-mn-cyrl.hyb
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6e82000-7007f6e91000 r--p 00000000 fe:00 1200                       /system/lib64/libutils.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   1 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f6e91000-7007f6e9d000 r-xp 0000f000 fe:00 1200                       /system/lib64/libutils.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   1 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-7007f6e9d000-7007f6e9e000 rw-p 0001b000 fe:00 1200                       /system/lib64/libutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6e9e000-7007f6e9f000 r--p 0001c000 fe:00 1200                       /system/lib64/libutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6e9f000-7007f6ea0000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ea1000-7007f6eb1000 r--s 00000000 fe:00 220                        /system/fonts/NotoSansVai-Regular.ttf
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6eb1000-7007f6eca000 r--s 00000000 fe:00 154                        /system/fonts/NotoSansLepcha-Regular.ttf
-Size:                100 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6eca000-7007f6ecb000 r--p 00000000 fe:00 1636                       /system/lib64/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f6ecb000-7007f6ecc000 r-xp 00001000 fe:00 1636                       /system/lib64/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6ecc000-7007f6ecd000 rw-p 00002000 fe:00 1636                       /system/lib64/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ecd000-7007f6ece000 r--p 00003000 fe:00 1636                       /system/lib64/android.hardware.graphics.common@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6ece000-7007f6ed0000 r--s 00000000 fe:00 986                        /system/usr/hyphen-data/hyph-fr.hyb
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6ed0000-7007f6edc000 r--s 00000000 fe:00 156                        /system/fonts/NotoSansTaiTham-Regular.ttf
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6edc000-7007f6efd000 r--s 00000000 fe:00 147                        /system/fonts/NotoSansBamum-Regular.ttf
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6efd000-7007f6f17000 r--s 00000000 fe:00 105                        /system/fonts/NotoSansMyanmarUI-Bold.ttf
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6f17000-7007f6f54000 r--p 00000000 fe:00 1563                       /system/lib64/libjpeg.so
-Size:                244 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                  15 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               15 kB
-VmFlags: rd mr mw me 
-7007f6f54000-7007f6fa6000 r-xp 0003d000 fe:00 1563                       /system/lib64/libjpeg.so
-Size:                328 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6fa6000-7007f6fa7000 rw-p 0008f000 fe:00 1563                       /system/lib64/libjpeg.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6fa7000-7007f6fa8000 r--p 00090000 fe:00 1563                       /system/lib64/libjpeg.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6fa8000-7007f6fa9000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6fa9000-7007f6faa000 r-xp 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me ac 
-7007f6faa000-7007f6ff5000 r--s 00000000 fe:00 121                        /system/fonts/Roboto-Medium.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 148 kB
-Pss:                  47 kB
-Shared_Clean:        148 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          148 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               47 kB
-VmFlags: rd mr me ms 
-7007f6ff5000-7007f6ff6000 r--p 00000000 fe:00 1623                       /system/lib64/libvndksupport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f6ff6000-7007f6ff7000 r-xp 00001000 fe:00 1623                       /system/lib64/libvndksupport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f6ff7000-7007f6ff8000 rw-p 00002000 fe:00 1623                       /system/lib64/libvndksupport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ff8000-7007f6ff9000 r--p 00003000 fe:00 1623                       /system/lib64/libvndksupport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f6ff9000-7007f6ffa000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ffa000-7007f6ffb000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f6ffb000-7007f6ffd000 r--s 00000000 fe:00 1014                       /system/usr/hyphen-data/hyph-da.hyb
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f6ffd000-7007f7001000 r--s 00000000 fe:00 199                        /system/fonts/NotoSansPahawhHmong-Regular.otf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7001000-7007f700e000 r--s 00000000 fe:00 159                        /system/fonts/NotoSansSyriacWestern-Regular.ttf
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f700e000-7007f7028000 r--s 00000000 fe:00 80                         /system/fonts/NotoSansMyanmarUI-Regular.ttf
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7028000-7007f702b000 r--p 00000000 fe:00 1747                       /system/lib64/libnetdbpf.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   2 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007f702b000-7007f7031000 r-xp 00003000 fe:00 1747                       /system/lib64/libnetdbpf.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7031000-7007f7032000 rw-p 00009000 fe:00 1747                       /system/lib64/libnetdbpf.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7032000-7007f7033000 r--p 0000a000 fe:00 1747                       /system/lib64/libnetdbpf.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7033000-7007f7034000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7034000-7007f7037000 r--s 00000000 fe:00 214                        /system/fonts/NotoSansPauCinHau-Regular.otf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7037000-7007f7044000 r--s 00000000 fe:00 194                        /system/fonts/NotoSansSyriacEastern-Regular.ttf
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7044000-7007f704b000 r--p 00000000 fe:00 1620                       /system/lib64/libmediametrics.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   3 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007f704b000-7007f7051000 r-xp 00007000 fe:00 1620                       /system/lib64/libmediametrics.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   4 kB
-Shared_Clean:         24 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me 
-7007f7051000-7007f7052000 rw-p 0000d000 fe:00 1620                       /system/lib64/libmediametrics.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7052000-7007f7054000 r--p 0000e000 fe:00 1620                       /system/lib64/libmediametrics.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7054000-7007f7055000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f7055000-7007f7058000 r--s 00000000 fe:00 141                        /system/fonts/NotoSansPalmyrene-Regular.otf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7058000-7007f707a000 r--s 00000000 fe:00 226                        /system/fonts/NotoSerifMyanmar-Bold.otf
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f707a000-7007f709c000 r--s 00000000 fe:00 153                        /system/fonts/NotoSerifMyanmar-Regular.otf
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f709c000-7007f70da000 r--p 00000000 fe:00 1512                       /system/lib64/libaudioclient.so
-Size:                248 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                  22 kB
-Shared_Clean:        128 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               22 kB
-VmFlags: rd mr mw me 
-7007f70da000-7007f7110000 r-xp 0003e000 fe:00 1512                       /system/lib64/libaudioclient.so
-Size:                216 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 188 kB
-Pss:                  41 kB
-Shared_Clean:        188 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          188 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               41 kB
-VmFlags: rd ex mr mw me 
-7007f7110000-7007f7111000 rw-p 00074000 fe:00 1512                       /system/lib64/libaudioclient.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7111000-7007f711f000 r--p 00075000 fe:00 1512                       /system/lib64/libaudioclient.so
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  56 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         56 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:            56 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-7007f711f000-7007f7120000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f7120000-7007f7126000 r--s 00000000 fe:00 108                        /system/fonts/NotoSansMiao-Regular.otf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7126000-7007f7132000 r--s 00000000 fe:00 206                        /system/fonts/NotoSansSyriacEstrangela-Regular.ttf
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7132000-7007f714d000 r--s 00000000 fe:00 227                        /system/fonts/NotoSansMyanmar-Bold.ttf
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f714d000-7007f7172000 r--p 00000000 fe:00 1732                       /system/lib64/libmedia_omx.so
-Size:                148 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 120 kB
-Pss:                  24 kB
-Shared_Clean:        120 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          120 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd mr mw me 
-7007f7172000-7007f7194000 r-xp 00025000 fe:00 1732                       /system/lib64/libmedia_omx.so
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 136 kB
-Pss:                  31 kB
-Shared_Clean:        136 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          136 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               31 kB
-VmFlags: rd ex mr mw me 
-7007f7194000-7007f7195000 rw-p 00047000 fe:00 1732                       /system/lib64/libmedia_omx.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7195000-7007f71a0000 r--p 00048000 fe:00 1732                       /system/lib64/libmedia_omx.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         44 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:            44 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me ac 
-7007f71a0000-7007f71a1000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f71a1000-7007f71a3000 r--s 00000000 fe:00 997                        /system/usr/hyphen-data/hyph-be.hyb
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f71a3000-7007f71be000 r--s 00000000 fe:00 187                        /system/fonts/NotoSansMyanmar-Regular.ttf
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f71be000-7007f71e2000 r--s 00000000 fe:00 180                        /system/fonts/NotoSansKhmer-VF.ttf
-Size:                144 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f71e2000-7007f71ea000 r--p 00000000 fe:00 1655                       /system/lib64/libselinux.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   0 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f71ea000-7007f71fa000 r-xp 00008000 fe:00 1655                       /system/lib64/libselinux.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   2 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-7007f71fa000-7007f71fb000 rw-p 00018000 fe:00 1655                       /system/lib64/libselinux.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f71fb000-7007f71fc000 r--p 00019000 fe:00 1655                       /system/lib64/libselinux.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f71fc000-7007f71fe000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007f71fe000-7007f7203000 r--s 00000000 fe:00 261                        /system/fonts/NotoSansMeroitic-Regular.otf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7203000-7007f7212000 r--s 00000000 fe:00 190                        /system/fonts/NotoSansLinearB-Regular.ttf
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7212000-7007f7219000 r--p 00000000 fe:00 1697                       /system/lib64/libpiex.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   6 kB
-Shared_Clean:         24 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007f7219000-7007f722c000 r-xp 00007000 fe:00 1697                       /system/lib64/libpiex.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f722c000-7007f722d000 rw-p 0001a000 fe:00 1697                       /system/lib64/libpiex.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f722d000-7007f722e000 r--p 0001b000 fe:00 1697                       /system/lib64/libpiex.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f722e000-7007f722f000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f722f000-7007f7238000 r--s 00000000 fe:00 259                        /system/fonts/NotoSansSymbols-Regular-Subsetted2.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7238000-7007f724d000 r--s 00000000 fe:00 72                         /system/fonts/NotoSansSinhalaUI-Bold.otf
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f724d000-7007f7262000 r--s 00000000 fe:00 241                        /system/fonts/NotoSansSinhalaUI-Regular.otf
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7262000-7007f726a000 r--p 00000000 fe:00 1240                       /system/lib64/libaudioutils.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   5 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f726a000-7007f7274000 r-xp 00008000 fe:00 1240                       /system/lib64/libaudioutils.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7274000-7007f7275000 rw-p 00012000 fe:00 1240                       /system/lib64/libaudioutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7275000-7007f7276000 r--p 00013000 fe:00 1240                       /system/lib64/libaudioutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7276000-7007f7277000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f7277000-7007f7286000 r--s 00000000 fe:00 186                        /system/fonts/NotoSansKaithi-Regular.ttf
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7286000-7007f7304000 r--p 00000000 fe:00 1125                       /system/lib64/libcrypto.so
-Size:                504 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 296 kB
-Pss:                  18 kB
-Shared_Clean:        296 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          296 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               18 kB
-VmFlags: rd mr mw me 
-7007f7304000-7007f73e2000 r-xp 0007e000 fe:00 1125                       /system/lib64/libcrypto.so
-Size:                888 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 752 kB
-Pss:                 256 kB
-Shared_Clean:        632 kB
-Shared_Dirty:          0 kB
-Private_Clean:       120 kB
-Private_Dirty:         0 kB
-Referenced:          752 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              256 kB
-VmFlags: rd ex mr mw me 
-7007f73e2000-7007f73e3000 rw-p 0015c000 fe:00 1125                       /system/lib64/libcrypto.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f73e3000-7007f73f4000 r--p 0015d000 fe:00 1125                       /system/lib64/libcrypto.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         68 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:            68 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-7007f73f4000-7007f73f6000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007f73f6000-7007f73fd000 r--s 00000000 fe:00 267                        /system/fonts/NotoSansPhagsPa-Regular.ttf
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f73fd000-7007f7423000 r--s 00000000 fe:00 129                        /system/fonts/NotoSansSinhala-Bold.ttf
-Size:                152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7423000-7007f7426000 r--p 00000000 fe:00 1569                       /system/lib64/libnativewindow.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   1 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f7426000-7007f7428000 r-xp 00003000 fe:00 1569                       /system/lib64/libnativewindow.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7428000-7007f7429000 rw-p 00005000 fe:00 1569                       /system/lib64/libnativewindow.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7429000-7007f742a000 r--p 00006000 fe:00 1569                       /system/lib64/libnativewindow.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f742a000-7007f7434000 r--s 00000000 fe:00 178                        /system/fonts/NotoSansJavanese-Regular.ttf
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7434000-7007f7449000 r--s 00000000 fe:00 198                        /system/fonts/NotoSerifSinhala-Bold.otf
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7449000-7007f7471000 r--s 00000000 fe:00 115                        /system/fonts/NotoSansSinhala-Regular.ttf
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7471000-7007f7473000 r--p 00000000 fe:00 1740                       /system/lib64/android.hidl.token@1.0-utils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f7473000-7007f7474000 r-xp 00002000 fe:00 1740                       /system/lib64/android.hidl.token@1.0-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7474000-7007f7475000 rw-p 00003000 fe:00 1740                       /system/lib64/android.hidl.token@1.0-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7475000-7007f7476000 r--p 00004000 fe:00 1740                       /system/lib64/android.hidl.token@1.0-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7476000-7007f7477000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7477000-7007f7486000 r--s 00000000 fe:00 76                         /system/fonts/NotoSansCherokee-Regular.ttf
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7486000-7007f7499000 r--s 00000000 fe:00 131                        /system/fonts/NotoSerifSinhala-Regular.otf
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7499000-7007f74ad000 r--s 00000000 fe:00 284                        /system/fonts/NotoSansOriyaUI-Bold.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f74ad000-7007f74c9000 r--p 00000000 fe:00 1562                       /system/lib64/android.hardware.cas@1.0.so
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  12 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-7007f74c9000-7007f74f5000 r-xp 0001c000 fe:00 1562                       /system/lib64/android.hardware.cas@1.0.so
-Size:                176 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f74f5000-7007f74f6000 rw-p 00048000 fe:00 1562                       /system/lib64/android.hardware.cas@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f74f6000-7007f74fb000 r--p 00049000 fe:00 1562                       /system/lib64/android.hardware.cas@1.0.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f74fb000-7007f7500000 r--s 00000000 fe:00 86                         /system/fonts/NotoSansManichaean-Regular.otf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7500000-7007f7514000 r--s 00000000 fe:00 244                        /system/fonts/NotoSansOriyaUI-Regular.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7514000-7007f7523000 r--p 00000000 fe:00 1198                       /system/lib64/libhidlbase.so
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  60 kB
-Pss:                   2 kB
-Shared_Clean:         60 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           60 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007f7523000-7007f7536000 r-xp 0000f000 fe:00 1198                       /system/lib64/libhidlbase.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  76 kB
-Pss:                   3 kB
-Shared_Clean:         76 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           76 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd ex mr mw me 
-7007f7536000-7007f7537000 rw-p 00022000 fe:00 1198                       /system/lib64/libhidlbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7537000-7007f7539000 r--p 00023000 fe:00 1198                       /system/lib64/libhidlbase.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7539000-7007f753a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f753a000-7007f753b000 rw-s 00000000 00:05 11403                      /dev/ashmem/GFXStats-1521 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr sh mr mw me ms 
-7007f753b000-7007f7547000 r--s 00000000 fe:00 283                        /system/fonts/NotoSansCanadianAboriginal-Regular.ttf
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7547000-7007f7558000 r--p 00000000 fe:00 1748                       /system/lib64/libpng.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  10 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007f7558000-7007f757e000 r-xp 00011000 fe:00 1748                       /system/lib64/libpng.so
-Size:                152 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 152 kB
-Pss:                  38 kB
-Shared_Clean:        152 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          152 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               38 kB
-VmFlags: rd ex mr mw me 
-7007f757e000-7007f757f000 rw-p 00037000 fe:00 1748                       /system/lib64/libpng.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f757f000-7007f7580000 r--p 00038000 fe:00 1748                       /system/lib64/libpng.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7580000-7007f75a0000 r--p 00000000 fe:00 1539                       /system/lib64/libpcre2.so
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                  20 kB
-Shared_Clean:        128 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd mr mw me 
-7007f75a0000-7007f75cf000 r-xp 00020000 fe:00 1539                       /system/lib64/libpcre2.so
-Size:                188 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 184 kB
-Pss:                  37 kB
-Shared_Clean:        184 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          184 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               37 kB
-VmFlags: rd ex mr mw me 
-7007f75cf000-7007f75d0000 rw-p 0004f000 fe:00 1539                       /system/lib64/libpcre2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f75d0000-7007f75d1000 r--p 00050000 fe:00 1539                       /system/lib64/libpcre2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f75d1000-7007f75d4000 r--s 00000000 fe:00 281                        /system/fonts/NotoSansOldPermic-Regular.otf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f75d4000-7007f75d8000 r--s 00000000 fe:00 268                        /system/fonts/NotoSansTifinagh-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f75d8000-7007f75ed000 r--s 00000000 fe:00 60                         /system/fonts/NotoSansOriya-Bold.ttf
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f75ed000-7007f7602000 r--s 00000000 fe:00 120                        /system/fonts/NotoSansOriya-Regular.ttf
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7602000-7007f760a000 r--p 00000000 fe:00 1141                       /system/lib64/libnetdutils.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   6 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007f760a000-7007f7614000 r-xp 00008000 fe:00 1141                       /system/lib64/libnetdutils.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7614000-7007f7615000 rw-p 00012000 fe:00 1141                       /system/lib64/libnetdutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7615000-7007f7616000 r--p 00013000 fe:00 1141                       /system/lib64/libnetdutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7616000-7007f7617000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7617000-7007f7619000 r--s 00000000 fe:00 277                        /system/fonts/NotoSansSoraSompeng-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7619000-7007f761d000 r--s 00000000 fe:00 225                        /system/fonts/NotoSansTaiViet-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f761d000-7007f7668000 r--s 00000000 fe:00 83                         /system/fonts/Roboto-Regular.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 208 kB
-Pss:                  55 kB
-Shared_Clean:        208 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          208 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               55 kB
-VmFlags: rd mr me ms 
-7007f7668000-7007f7909000 r--p 00000000 fe:00 1705                       /system/lib64/libpdfium.so
-Size:               2692 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                  37 kB
-Shared_Clean:        128 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               37 kB
-VmFlags: rd mr mw me 
-7007f7909000-7007f7b59000 r-xp 002a1000 fe:00 1705                       /system/lib64/libpdfium.so
-Size:               2368 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7b59000-7007f7b5d000 rw-p 004f1000 fe:00 1705                       /system/lib64/libpdfium.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7b5d000-7007f7b72000 r--p 004f5000 fe:00 1705                       /system/lib64/libpdfium.so
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  84 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         84 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            84 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f7b72000-7007f7b7a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7b7a000-7007f7b7c000 r--s 00000000 fe:00 230                        /system/fonts/NotoSansOldNorthArabian-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7b7c000-7007f7b85000 r--s 00000000 fe:00 137                        /system/fonts/NotoSansChakma-Regular.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7b85000-7007f7b9c000 r--s 00000000 fe:00 210                        /system/fonts/NotoSerifKannada-Bold.ttf
-Size:                 92 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7b9c000-7007f7bb3000 r--s 00000000 fe:00 160                        /system/fonts/NotoSerifKannada-Regular.ttf
-Size:                 92 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7bb3000-7007f7bcd000 r--p 00000000 fe:00 1595                       /system/lib64/libwilhelm.so
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  10 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007f7bcd000-7007f7bed000 r-xp 0001a000 fe:00 1595                       /system/lib64/libwilhelm.so
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7bed000-7007f7bee000 rw-p 0003a000 fe:00 1595                       /system/lib64/libwilhelm.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7bee000-7007f7bf3000 r--p 0003b000 fe:00 1595                       /system/lib64/libwilhelm.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f7bf3000-7007f7bf4000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7bf4000-7007f7bf6000 r--s 00000000 fe:00 213                        /system/fonts/NotoSansNabataean-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7bf6000-7007f7c0a000 r--s 00000000 fe:00 169                        /system/fonts/NotoSansKannadaUI-Bold.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7c0a000-7007f7c96000 r--p 00000000 fe:00 1659                       /system/lib64/libstagefright.so
-Size:                560 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 256 kB
-Pss:                  66 kB
-Shared_Clean:        256 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          256 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               66 kB
-VmFlags: rd mr mw me 
-7007f7c96000-7007f7dad000 r-xp 0008c000 fe:00 1659                       /system/lib64/libstagefright.so
-Size:               1116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 788 kB
-Pss:                 289 kB
-Shared_Clean:        788 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          788 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              289 kB
-VmFlags: rd ex mr mw me 
-7007f7dad000-7007f7dae000 rw-p 001a3000 fe:00 1659                       /system/lib64/libstagefright.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7dae000-7007f7dbe000 r--p 001a4000 fe:00 1659                       /system/lib64/libstagefright.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         64 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:            64 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-7007f7dbe000-7007f7dbf000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f7dbf000-7007f7ddb000 r--s 00000000 fe:00 291                        /system/fonts/NotoSansTeluguUI-Bold.ttf
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7ddb000-7007f7de5000 r--p 00000000 fe:00 1770                       /system/lib64/android.hidl.allocator@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   6 kB
-Shared_Clean:         40 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007f7de5000-7007f7def000 r-xp 0000a000 fe:00 1770                       /system/lib64/android.hidl.allocator@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   7 kB
-Shared_Clean:         40 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd ex mr mw me 
-7007f7def000-7007f7df0000 rw-p 00014000 fe:00 1770                       /system/lib64/android.hidl.allocator@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7df0000-7007f7df2000 r--p 00015000 fe:00 1770                       /system/lib64/android.hidl.allocator@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7df2000-7007f7df3000 rw-s 00000000 00:05 11403                      /dev/ashmem/GFXStats-1521 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr sh mr mw me ms 
-7007f7df3000-7007f7e07000 r--s 00000000 fe:00 236                        /system/fonts/NotoSansKannadaUI-Regular.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7e07000-7007f7e10000 r--p 00000000 fe:00 1203                       /system/lib64/liblzma.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   3 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007f7e10000-7007f7e2f000 r-xp 00009000 fe:00 1203                       /system/lib64/liblzma.so
-Size:                124 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7e2f000-7007f7e30000 rw-p 00028000 fe:00 1203                       /system/lib64/liblzma.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7e30000-7007f7e31000 r--p 00029000 fe:00 1203                       /system/lib64/liblzma.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7e31000-7007f7e38000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7e38000-7007f7e3d000 r--s 00000000 fe:00 269                        /system/fonts/NotoSansSaurashtra-Regular.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7e3d000-7007f7e45000 r--s 00000000 fe:00 204                        /system/fonts/NotoSansBalinese-Regular.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7e45000-7007f7e50000 r--p 00000000 fe:00 1544                       /system/lib64/android.hidl.token@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   5 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f7e50000-7007f7e5b000 r-xp 0000b000 fe:00 1544                       /system/lib64/android.hidl.token@1.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7e5b000-7007f7e5c000 rw-p 00016000 fe:00 1544                       /system/lib64/android.hidl.token@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7e5c000-7007f7e5e000 r--p 00017000 fe:00 1544                       /system/lib64/android.hidl.token@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7e5e000-7007f7e60000 r--s 00000000 fe:00 85                         /system/fonts/NotoSansMultani-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7e60000-7007f7e65000 r--s 00000000 fe:00 168                        /system/fonts/NotoSansNKo-Regular.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7e65000-7007f7eb7000 r--s 00000000 fe:00 165                        /system/fonts/Roboto-LightItalic.ttf
-Size:                328 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7eb7000-7007f7ed5000 r--p 00000000 fe:00 1126                       /system/lib64/libprotobuf-cpp-lite.so
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  96 kB
-Pss:                   8 kB
-Shared_Clean:         96 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           96 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me 
-7007f7ed5000-7007f7ef4000 r-xp 0001e000 fe:00 1126                       /system/lib64/libprotobuf-cpp-lite.so
-Size:                124 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                  11 kB
-Shared_Clean:        124 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          124 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               11 kB
-VmFlags: rd ex mr mw me 
-7007f7ef4000-7007f7ef5000 rw-p 0003d000 fe:00 1126                       /system/lib64/libprotobuf-cpp-lite.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7ef5000-7007f7ef7000 r--p 0003e000 fe:00 1126                       /system/lib64/libprotobuf-cpp-lite.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7ef7000-7007f7ef8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7ef8000-7007f7ef9000 r--p 00000000 00:00 0                          [anon:atexit handlers]
-Name:           [anon:atexit handlers]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f7ef9000-7007f7f0d000 r--s 00000000 fe:00 111                        /system/fonts/NotoSansKannada-Bold.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7f0d000-7007f7f19000 r--p 00000000 fe:00 1208                       /system/lib64/libbufferhubqueue.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   6 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007f7f19000-7007f7f2a000 r-xp 0000c000 fe:00 1208                       /system/lib64/libbufferhubqueue.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7f2a000-7007f7f2b000 rw-p 0001d000 fe:00 1208                       /system/lib64/libbufferhubqueue.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7f2b000-7007f7f2c000 r--p 0001e000 fe:00 1208                       /system/lib64/libbufferhubqueue.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7f2c000-7007f7f2d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7f2d000-7007f7f2e000 rw-s 00000000 00:05 9940                       /dev/ashmem/0f02fd80-4c97-473b-981d-e08369625636 (deleted)
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr sh mr mw ms 
-7007f7f2e000-7007f7f30000 r--s 00000000 fe:00 112                        /system/fonts/NotoSansMro-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7f30000-7007f7f71000 r--s 00000000 fe:00 62                         /system/fonts/NotoSerif-BoldItalic.ttf
-Size:                260 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7f71000-7007f7f72000 r--p 00000000 fe:00 1177                       /system/lib64/libsync.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f7f72000-7007f7f73000 r-xp 00001000 fe:00 1177                       /system/lib64/libsync.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f7f73000-7007f7f74000 rw-p 00002000 fe:00 1177                       /system/lib64/libsync.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7f74000-7007f7f75000 r--p 00003000 fe:00 1177                       /system/lib64/libsync.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f7f75000-7007f7f76000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f7f76000-7007f7f7a000 r--s 00000000 fe:00 99                         /system/fonts/NotoSansSylotiNagri-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7f7a000-7007f7f87000 r--s 00000000 fe:00 125                        /system/fonts/NotoSansAdlam-Regular.ttf
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f7f87000-7007f7fd1000 r--p 00000000 fe:00 1597                       /system/lib64/libc.so
-Size:                296 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 228 kB
-Pss:                   3 kB
-Shared_Clean:        228 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          228 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007f7fd1000-7007f8089000 r-xp 0004a000 fe:00 1597                       /system/lib64/libc.so
-Size:                736 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 728 kB
-Pss:                  12 kB
-Shared_Clean:        728 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          728 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me 
-7007f8089000-7007f808c000 rw-p 00102000 fe:00 1597                       /system/lib64/libc.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007f808c000-7007f8093000 r--p 00105000 fe:00 1597                       /system/lib64/libc.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         28 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f8093000-7007f80e5000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                328 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  40 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:        40 kB
-Referenced:           48 kB
-Anonymous:            48 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               40 kB
-VmFlags: rd wr mr mw me ac 
-7007f80e5000-7007f80e6000 r--p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f80e6000-7007f80eb000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  20 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        20 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd wr mr mw me ac 
-7007f80eb000-7007f80ec000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f80ec000-7007f80ee000 r--s 00000000 fe:00 209                        /system/fonts/NotoSansHatran-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f80ee000-7007f810a000 r--s 00000000 fe:00 181                        /system/fonts/NotoSansTeluguUI-Regular.ttf
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f810a000-7007f8113000 r--p 00000000 fe:00 1515                       /system/lib64/libsoundtrigger.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   9 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f8113000-7007f8118000 r-xp 00009000 fe:00 1515                       /system/lib64/libsoundtrigger.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                  10 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd ex mr mw me 
-7007f8118000-7007f8119000 rw-p 0000e000 fe:00 1515                       /system/lib64/libsoundtrigger.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8119000-7007f811d000 r--p 0000f000 fe:00 1515                       /system/lib64/libsoundtrigger.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f811d000-7007f811e000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f811e000-7007f8122000 r--s 00000000 fe:00 107                        /system/fonts/NotoSansOldPersian-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8122000-7007f812a000 r--s 00000000 fe:00 116                        /system/fonts/NotoSansLaoUI-Bold.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f812a000-7007f814f000 r--s 00000000 fe:00 252                        /system/fonts/NotoSerifTelugu-Bold.ttf
-Size:                148 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f814f000-7007f815d000 r--p 00000000 fe:00 1190                       /system/lib64/libexpat.so
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  56 kB
-Pss:                   9 kB
-Shared_Clean:         56 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           56 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f815d000-7007f8178000 r-xp 0000e000 fe:00 1190                       /system/lib64/libexpat.so
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f8178000-7007f8179000 rw-p 00029000 fe:00 1190                       /system/lib64/libexpat.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8179000-7007f817b000 r--p 0002a000 fe:00 1190                       /system/lib64/libexpat.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f817b000-7007f817c000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f817c000-7007f8182000 r--s 00000000 fe:00 188                        /system/fonts/NotoSansKharoshthi-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8182000-7007f81c5000 r--p 00000000 fe:00 1204                       /system/lib64/libmedia.so
-Size:                268 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                  21 kB
-Shared_Clean:        128 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-7007f81c5000-7007f821a000 r-xp 00043000 fe:00 1204                       /system/lib64/libmedia.so
-Size:                340 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 272 kB
-Pss:                  65 kB
-Shared_Clean:        272 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          272 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               65 kB
-VmFlags: rd ex mr mw me 
-7007f821a000-7007f821b000 rw-p 00098000 fe:00 1204                       /system/lib64/libmedia.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f821b000-7007f8230000 r--p 00099000 fe:00 1204                       /system/lib64/libmedia.so
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  84 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         84 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:            84 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f8230000-7007f8231000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8231000-7007f8232000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f8232000-7007f8257000 r--s 00000000 fe:00 203                        /system/fonts/NotoSerifTelugu-Regular.ttf
-Size:                148 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8257000-7007f8264000 r--p 00000000 fe:00 1700                       /system/lib64/android.hardware.graphics.mapper@2.1.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                   5 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f8264000-7007f8271000 r-xp 0000d000 fe:00 1700                       /system/lib64/android.hardware.graphics.mapper@2.1.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                   6 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-7007f8271000-7007f8272000 rw-p 0001a000 fe:00 1700                       /system/lib64/android.hardware.graphics.mapper@2.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8272000-7007f8274000 r--p 0001b000 fe:00 1700                       /system/lib64/android.hardware.graphics.mapper@2.1.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f8274000-7007f827a000 r--s 00000000 fe:00 106                        /system/fonts/NotoSansCoptic-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f827a000-7007f8282000 r--s 00000000 fe:00 59                         /system/fonts/NotoSansLaoUI-Regular.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8282000-7007f8296000 r--p 00000000 fe:00 1216                       /system/lib64/android.system.suspend@1.0.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   9 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f8296000-7007f82ae000 r-xp 00014000 fe:00 1216                       /system/lib64/android.system.suspend@1.0.so
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  96 kB
-Pss:                  19 kB
-Shared_Clean:         96 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           96 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               19 kB
-VmFlags: rd ex mr mw me 
-7007f82ae000-7007f82af000 rw-p 0002c000 fe:00 1216                       /system/lib64/android.system.suspend@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f82af000-7007f82b3000 r--p 0002d000 fe:00 1216                       /system/lib64/android.system.suspend@1.0.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f82b3000-7007f82b4000 r--s 00000000 00:13 6990                       /dev/event-log-tags
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f82b4000-7007f82ba000 r--s 00000000 fe:00 242                        /system/fonts/NotoSansBrahmi-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f82ba000-7007f82c4000 r--s 00000000 fe:00 92                         /system/fonts/NotoSansKhmerUI-Regular.ttf
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f82c4000-7007f82c5000 r--p 00000000 fe:00 1217                       /system/lib64/libhidlallocatorutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f82c5000-7007f82c6000 r-xp 00001000 fe:00 1217                       /system/lib64/libhidlallocatorutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f82c6000-7007f82c7000 rw-p 00002000 fe:00 1217                       /system/lib64/libhidlallocatorutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f82c7000-7007f82c8000 r--p 00003000 fe:00 1217                       /system/lib64/libhidlallocatorutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f82c8000-7007f82ce000 r--s 00000000 fe:00 101                        /system/fonts/NotoSansCham-Bold.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f82ce000-7007f82da000 r--s 00000000 fe:00 228                        /system/fonts/NotoSerifKhmer-Bold.otf
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f82da000-7007f832b000 r--s 00000000 fe:00 89                         /system/fonts/Roboto-ThinItalic.ttf
-Size:                324 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f832b000-7007f835c000 r--p 00000000 fe:00 1152                       /system/lib64/libvintf.so
-Size:                196 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                  32 kB
-Shared_Clean:        124 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          124 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd mr mw me 
-7007f835c000-7007f83b7000 r-xp 00031000 fe:00 1152                       /system/lib64/libvintf.so
-Size:                364 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 360 kB
-Pss:                 138 kB
-Shared_Clean:        352 kB
-Shared_Dirty:          0 kB
-Private_Clean:         8 kB
-Private_Dirty:         0 kB
-Referenced:          360 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              138 kB
-VmFlags: rd ex mr mw me 
-7007f83b7000-7007f83b8000 rw-p 0008c000 fe:00 1152                       /system/lib64/libvintf.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f83b8000-7007f83bd000 r--p 0008d000 fe:00 1152                       /system/lib64/libvintf.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f83bd000-7007f83bf000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007f83bf000-7007f83c2000 r--s 00000000 fe:00 287                        /system/fonts/NotoSansTaiLe-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f83c2000-7007f85b0000 r--p 00000000 fe:00 1537                       /system/lib64/libhwui.so
-Size:               1976 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 632 kB
-Pss:                 196 kB
-Shared_Clean:        632 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          632 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              196 kB
-VmFlags: rd mr mw me 
-7007f85b0000-7007f8b9b000 r-xp 001ee000 fe:00 1537                       /system/lib64/libhwui.so
-Size:               6060 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                4132 kB
-Pss:                1274 kB
-Shared_Clean:       4132 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         4132 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1274 kB
-VmFlags: rd ex mr mw me 
-7007f8b9b000-7007f8b9c000 rw-p 007d9000 fe:00 1537                       /system/lib64/libhwui.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f8b9c000-7007f8bd5000 r--p 007da000 fe:00 1537                       /system/lib64/libhwui.so
-Size:                228 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 228 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        228 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          160 kB
-Anonymous:           228 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me ac 
-7007f8bd5000-7007f8bda000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  16 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        16 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd wr mr mw me ac 
-7007f8bda000-7007f8bde000 r--s 00000000 fe:00 126                        /system/fonts/NotoSansNewTaiLue-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8bde000-7007f8bf3000 r--s 00000000 fe:00 90                         /system/fonts/NotoSansKannada-Regular.ttf
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8bf3000-7007f8c0e000 r--s 00000000 fe:00 118                        /system/fonts/NotoSansTelugu-Bold.ttf
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8c0e000-7007f8cfe000 r--p 00000000 fe:00 1538                       /system/lib64/libicui18n.so
-Size:                960 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 192 kB
-Pss:                  21 kB
-Shared_Clean:        192 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          192 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd mr mw me 
-7007f8cfe000-7007f8e8a000 r-xp 000f0000 fe:00 1538                       /system/lib64/libicui18n.so
-Size:               1584 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                1276 kB
-Pss:                 318 kB
-Shared_Clean:       1276 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         1276 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              318 kB
-VmFlags: rd ex mr mw me 
-7007f8e8a000-7007f8e8b000 rw-p 0027c000 fe:00 1538                       /system/lib64/libicui18n.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8e8b000-7007f8e9e000 r--p 0027d000 fe:00 1538                       /system/lib64/libicui18n.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  76 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         76 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:            76 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f8e9e000-7007f8e9f000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f8e9f000-7007f8ea7000 r--s 00000000 fe:00 95                         /system/fonts/NotoSerifLao-Bold.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8ea7000-7007f8ec3000 r--s 00000000 fe:00 221                        /system/fonts/NotoSansTelugu-Regular.ttf
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8ec3000-7007f8edd000 r--s 00000000 fe:00 64                         /system/fonts/NotoSansBengaliUI-Bold.ttf
-Size:                104 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8edd000-7007f8edf000 r--p 00000000 fe:00 1743                       /system/lib64/libstagefright_codecbase.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   1 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f8edf000-7007f8ee2000 r-xp 00002000 fe:00 1743                       /system/lib64/libstagefright_codecbase.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   6 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-7007f8ee2000-7007f8ee3000 rw-p 00005000 fe:00 1743                       /system/lib64/libstagefright_codecbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8ee3000-7007f8ee4000 r--p 00006000 fe:00 1743                       /system/lib64/libstagefright_codecbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f8ee4000-7007f8ee7000 r--s 00000000 fe:00 176                        /system/fonts/NotoSansSundanese-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8ee7000-7007f8f04000 r--s 00000000 fe:00 197                        /system/fonts/NotoSerifBengali-Bold.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8f04000-7007f8f05000 r--p 00000000 fe:00 1151                       /system/lib64/libion.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f8f05000-7007f8f06000 r-xp 00001000 fe:00 1151                       /system/lib64/libion.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f8f06000-7007f8f07000 rw-p 00002000 fe:00 1151                       /system/lib64/libion.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8f07000-7007f8f08000 r--p 00003000 fe:00 1151                       /system/lib64/libion.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f8f08000-7007f8f09000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f8f09000-7007f8f0a000 r--s 00000000 fe:00 996                        /system/usr/hyphen-data/hyph-und-ethi.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8f0a000-7007f8f55000 r--s 00000000 fe:00 237                        /system/fonts/Roboto-Light.ttf
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f8f55000-7007f9019000 r--p 00000000 fe:00 1195                       /system/lib64/libandroid_runtime.so
-Size:                784 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 448 kB
-Pss:                  78 kB
-Shared_Clean:        448 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          448 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               78 kB
-VmFlags: rd mr mw me 
-7007f9019000-7007f910c000 r-xp 000c4000 fe:00 1195                       /system/lib64/libandroid_runtime.so
-Size:                972 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 772 kB
-Pss:                  68 kB
-Shared_Clean:        772 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          772 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               68 kB
-VmFlags: rd ex mr mw me 
-7007f910c000-7007f910d000 rw-p 001b7000 fe:00 1195                       /system/lib64/libandroid_runtime.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f910d000-7007f912a000 r--p 001b8000 fe:00 1195                       /system/lib64/libandroid_runtime.so
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 116 kB
-Pss:                   6 kB
-Shared_Clean:          0 kB
-Shared_Dirty:        116 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           72 kB
-Anonymous:           116 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me ac 
-7007f912a000-7007f912d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-7007f912d000-7007f9148000 r--s 00000000 fe:00 67                         /system/fonts/NotoSansBengaliUI-Regular.ttf
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9148000-7007f9158000 r--p 00000000 fe:00 1761                       /system/lib64/android.hardware.configstore@1.0.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   6 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007f9158000-7007f916c000 r-xp 00010000 fe:00 1761                       /system/lib64/android.hardware.configstore@1.0.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                  10 kB
-Shared_Clean:         80 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd ex mr mw me 
-7007f916c000-7007f916d000 rw-p 00024000 fe:00 1761                       /system/lib64/android.hardware.configstore@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f916d000-7007f9170000 r--p 00025000 fe:00 1761                       /system/lib64/android.hardware.configstore@1.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9170000-7007f9172000 r--s 00000000 fe:00 79                         /system/fonts/NotoSansBassaVah-Regular.otf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9172000-7007f918f000 r--s 00000000 fe:00 246                        /system/fonts/NotoSerifBengali-Regular.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f918f000-7007f91b2000 r--p 00000000 fe:00 1581                       /system/lib64/libsqlite.so
-Size:                140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   7 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007f91b2000-7007f92b8000 r-xp 00023000 fe:00 1581                       /system/lib64/libsqlite.so
-Size:               1048 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 916 kB
-Pss:                 111 kB
-Shared_Clean:        916 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          916 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              111 kB
-VmFlags: rd ex mr mw me 
-7007f92b8000-7007f92ba000 rw-p 00129000 fe:00 1581                       /system/lib64/libsqlite.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f92ba000-7007f92bd000 r--p 0012b000 fe:00 1581                       /system/lib64/libsqlite.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f92bd000-7007f92be000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f92be000-7007f92c1000 r--s 00000000 fe:00 65                         /system/fonts/NotoSansSamaritan-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f92c1000-7007f92cb000 r--s 00000000 fe:00 174                        /system/fonts/NotoSerifKhmer-Regular.otf
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f92cb000-7007f92ed000 r--p 00000000 fe:00 1127                       /system/lib64/libm.so
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 136 kB
-Pss:                   7 kB
-Shared_Clean:        136 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          136 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007f92ed000-7007f9319000 r-xp 00022000 fe:00 1127                       /system/lib64/libm.so
-Size:                176 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 100 kB
-Pss:                   4 kB
-Shared_Clean:        100 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          100 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me 
-7007f9319000-7007f931a000 rw-p 0004e000 fe:00 1127                       /system/lib64/libm.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f931a000-7007f931b000 r--p 0004f000 fe:00 1127                       /system/lib64/libm.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f931b000-7007f931c000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f931c000-7007f9366000 r--s 00000000 fe:00 175                        /system/fonts/RobotoCondensed-Light.ttf
-Size:                296 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9366000-7007f936e000 r--p 00000000 fe:00 1260                       /system/lib64/libcutils.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   0 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f936e000-7007f9377000 r-xp 00008000 fe:00 1260                       /system/lib64/libcutils.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   0 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9377000-7007f9378000 rw-p 00011000 fe:00 1260                       /system/lib64/libcutils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f9378000-7007f937a000 r--p 00012000 fe:00 1260                       /system/lib64/libcutils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f937a000-7007f937b000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f937b000-7007f937c000 r--s 00000000 fe:00 1018                       /system/usr/hyphen-data/hyph-tk.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f937c000-7007f9384000 r--s 00000000 fe:00 117                        /system/fonts/NotoSerifLao-Regular.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9384000-7007f93b3000 r--p 00000000 fe:00 1598                       /system/lib64/libft2.so
-Size:                188 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                  26 kB
-Shared_Clean:        128 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               26 kB
-VmFlags: rd mr mw me 
-7007f93b3000-7007f9422000 r-xp 0002f000 fe:00 1598                       /system/lib64/libft2.so
-Size:                444 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 376 kB
-Pss:                  94 kB
-Shared_Clean:        376 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          376 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               94 kB
-VmFlags: rd ex mr mw me 
-7007f9422000-7007f9423000 rw-p 0009e000 fe:00 1598                       /system/lib64/libft2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9423000-7007f9428000 r--p 0009f000 fe:00 1598                       /system/lib64/libft2.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f9428000-7007f942c000 r--s 00000000 fe:00 217                        /system/fonts/NotoSansMeeteiMayek-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f942c000-7007f9445000 r--s 00000000 fe:00 127                        /system/fonts/NotoSansBengali-Bold.ttf
-Size:                100 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9445000-7007f9452000 r--p 00000000 fe:00 1520                       /system/lib64/libhidl-gen-utils.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                   5 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f9452000-7007f9467000 r-xp 0000d000 fe:00 1520                       /system/lib64/libhidl-gen-utils.so
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  84 kB
-Pss:                  11 kB
-Shared_Clean:         84 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           84 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               11 kB
-VmFlags: rd ex mr mw me 
-7007f9467000-7007f9468000 rw-p 00022000 fe:00 1520                       /system/lib64/libhidl-gen-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9468000-7007f9469000 r--p 00023000 fe:00 1520                       /system/lib64/libhidl-gen-utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9469000-7007f946a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f946a000-7007f946c000 r--s 00000000 fe:00 272                        /system/fonts/NotoSansUgaritic-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f946c000-7007f9485000 r--s 00000000 fe:00 183                        /system/fonts/NotoSansBengali-Regular.ttf
-Size:                100 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9485000-7007f9493000 r--s 00000000 fe:00 94                         /system/fonts/NotoSansMalayalamUI-Bold.ttf
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9493000-7007f9495000 r--p 00000000 fe:00 1189                       /system/lib64/libnativebridge.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f9495000-7007f9497000 r-xp 00002000 fe:00 1189                       /system/lib64/libnativebridge.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9497000-7007f9498000 rw-p 00004000 fe:00 1189                       /system/lib64/libnativebridge.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9498000-7007f9499000 r--p 00005000 fe:00 1189                       /system/lib64/libnativebridge.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9499000-7007f949a000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f949a000-7007f949e000 r--s 00000000 fe:00 145                        /system/fonts/NotoSansMandaic-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f949e000-7007f94ac000 r--s 00000000 fe:00 133                        /system/fonts/NotoSansMalayalamUI-Regular.ttf
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f94ac000-7007f94b9000 r--s 00000000 fe:00 232                        /system/fonts/NotoSerifMalayalam-Bold.ttf
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f94b9000-7007f94c7000 r--s 00000000 fe:00 273                        /system/fonts/NotoSansMalayalam-Bold.ttf
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f94c7000-7007f94f3000 r--p 00000000 fe:00 1702                       /system/lib64/libharfbuzz_ng.so
-Size:                176 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 156 kB
-Pss:                  33 kB
-Shared_Clean:        156 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          156 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               33 kB
-VmFlags: rd mr mw me 
-7007f94f3000-7007f9570000 r-xp 0002c000 fe:00 1702                       /system/lib64/libharfbuzz_ng.so
-Size:                500 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 488 kB
-Pss:                 122 kB
-Shared_Clean:        488 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          488 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              122 kB
-VmFlags: rd ex mr mw me 
-7007f9570000-7007f9571000 rw-p 000a9000 fe:00 1702                       /system/lib64/libharfbuzz_ng.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9571000-7007f9572000 r--p 000aa000 fe:00 1702                       /system/lib64/libharfbuzz_ng.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9572000-7007f9575000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9575000-7007f957e000 r--s 00000000 fe:00 212                        /system/fonts/NotoSansKhmerUI-Bold.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f957e000-7007f958c000 r--s 00000000 fe:00 150                        /system/fonts/NotoSansMalayalam-Regular.ttf
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f958c000-7007f958e000 r--p 00000000 fe:00 1640                       /system/lib64/libmemtrack.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f958e000-7007f958f000 r-xp 00002000 fe:00 1640                       /system/lib64/libmemtrack.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd ex mr mw me 
-7007f958f000-7007f9590000 rw-p 00003000 fe:00 1640                       /system/lib64/libmemtrack.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9590000-7007f9591000 r--p 00004000 fe:00 1640                       /system/lib64/libmemtrack.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9591000-7007f9592000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f9592000-7007f959f000 r--s 00000000 fe:00 109                        /system/fonts/NotoSerifMalayalam-Regular.ttf
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f959f000-7007f95a8000 r--s 00000000 fe:00 163                        /system/fonts/NotoSansTamilUI-Bold.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f95a8000-7007f95f4000 r--s 00000000 fe:00 251                        /system/fonts/Roboto-Thin.ttf
-Size:                304 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f95f4000-7007f95f6000 r--p 00000000 fe:00 1657                       /system/lib64/libdebuggerd_client.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   1 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f95f6000-7007f95f8000 r-xp 00002000 fe:00 1657                       /system/lib64/libdebuggerd_client.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f95f8000-7007f95f9000 rw-p 00004000 fe:00 1657                       /system/lib64/libdebuggerd_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f95f9000-7007f95fa000 r--p 00005000 fe:00 1657                       /system/lib64/libdebuggerd_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f95fa000-7007f95fe000 r--s 00000000 fe:00 201                        /system/fonts/NotoSansGlagolitic-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f95fe000-7007f961a000 r--s 00000000 fe:00 69                         /system/fonts/NotoSansGujaratiUI-Bold.ttf
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f961a000-7007f961b000 r--p 00000000 fe:00 1652                       /system/lib64/libdl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f961b000-7007f961c000 r-xp 00001000 fe:00 1652                       /system/lib64/libdl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f961c000-7007f961d000 r--p 00002000 fe:00 1652                       /system/lib64/libdl.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f961d000-7007f961e000 r--p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f961e000-7007f9624000 r--s 00000000 fe:00 173                        /system/fonts/NotoSansCham-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9624000-7007f9642000 r--s 00000000 fe:00 271                        /system/fonts/NotoSansGujarati-Regular.ttf
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9642000-7007f9648000 r--p 00000000 fe:00 1769                       /system/lib64/libbpf_android.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   4 kB
-Shared_Clean:         24 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007f9648000-7007f9652000 r-xp 00006000 fe:00 1769                       /system/lib64/libbpf_android.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   2 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-7007f9652000-7007f9653000 rw-p 00010000 fe:00 1769                       /system/lib64/libbpf_android.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9653000-7007f9654000 r--p 00011000 fe:00 1769                       /system/lib64/libbpf_android.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9654000-7007f9655000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9655000-7007f9657000 r--s 00000000 fe:00 177                        /system/fonts/NotoSansTagbanwa-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9657000-7007f9660000 r--s 00000000 fe:00 75                         /system/fonts/NotoSansTamilUI-Regular.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9660000-7007f969d000 r--s 00000000 fe:00 140                        /system/fonts/NotoSerif-Italic.ttf
-Size:                244 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f969d000-7007f969f000 r--p 00000000 fe:00 1718                       /system/lib64/libstdc++.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f969f000-7007f96a1000 r-xp 00002000 fe:00 1718                       /system/lib64/libstdc++.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f96a1000-7007f96a2000 rw-p 00004000 fe:00 1718                       /system/lib64/libstdc++.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f96a2000-7007f96a3000 r--p 00005000 fe:00 1718                       /system/lib64/libstdc++.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f96a3000-7007f96c0000 r--s 00000000 fe:00 256                        /system/fonts/NotoSansGujaratiUI-Regular.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f96c0000-7007f96de000 r--s 00000000 fe:00 93                         /system/fonts/NotoSansDevanagariUI-Bold.ttf
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f96de000-7007f9717000 r--p 00000000 fe:00 1547                       /system/lib64/libhidltransport.so
-Size:                228 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 200 kB
-Pss:                   9 kB
-Shared_Clean:        200 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          200 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007f9717000-7007f9772000 r-xp 00039000 fe:00 1547                       /system/lib64/libhidltransport.so
-Size:                364 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 364 kB
-Pss:                  16 kB
-Shared_Clean:        364 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          364 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               16 kB
-VmFlags: rd ex mr mw me 
-7007f9772000-7007f9773000 rw-p 00094000 fe:00 1547                       /system/lib64/libhidltransport.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9773000-7007f977d000 r--p 00095000 fe:00 1547                       /system/lib64/libhidltransport.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         40 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:            40 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me ac 
-7007f977d000-7007f977e000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f977e000-7007f9786000 r--s 00000000 fe:00 185                        /system/fonts/NotoSansLao-Bold.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9786000-7007f978f000 r--s 00000000 fe:00 245                        /system/fonts/NotoSerifTamil-Bold.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f978f000-7007f9798000 r--s 00000000 fe:00 191                        /system/fonts/NotoSerifTamil-Regular.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9798000-7007f97b7000 r--s 00000000 fe:00 248                        /system/fonts/NotoSansDevanagariUI-Regular.ttf
-Size:                124 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f97b7000-7007f986a000 r--p 00000000 fe:00 1267                       /system/lib64/libicuuc.so
-Size:                716 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 440 kB
-Pss:                  45 kB
-Shared_Clean:        440 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          440 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               45 kB
-VmFlags: rd mr mw me 
-7007f986a000-7007f9966000 r-xp 000b3000 fe:00 1267                       /system/lib64/libicuuc.so
-Size:               1008 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 992 kB
-Pss:                  73 kB
-Shared_Clean:        992 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          992 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               73 kB
-VmFlags: rd ex mr mw me 
-7007f9966000-7007f9967000 rw-p 001af000 fe:00 1267                       /system/lib64/libicuuc.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9967000-7007f997b000 r--p 001b0000 fe:00 1267                       /system/lib64/libicuuc.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         80 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:            80 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007f997b000-7007f997d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007f997d000-7007f997e000 r--s 00000000 fe:00 977                        /system/usr/hyphen-data/hyph-te.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f997e000-7007f9987000 r--s 00000000 fe:00 70                         /system/fonts/NotoSansTamil-Bold.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9987000-7007f99a8000 r--s 00000000 fe:00 124                        /system/fonts/NotoSansDevanagari-Bold.ttf
-Size:                132 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f99a8000-7007f99ac000 r--p 00000000 fe:00 1542                       /system/lib64/libstagefright_xmlparser.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   3 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007f99ac000-7007f99b4000 r-xp 00004000 fe:00 1542                       /system/lib64/libstagefright_xmlparser.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f99b4000-7007f99b5000 rw-p 0000c000 fe:00 1542                       /system/lib64/libstagefright_xmlparser.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f99b5000-7007f99b6000 r--p 0000d000 fe:00 1542                       /system/lib64/libstagefright_xmlparser.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f99b6000-7007f99b8000 r--s 00000000 fe:00 234                        /system/fonts/NotoSansTagalog-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f99b8000-7007f99da000 r--s 00000000 fe:00 235                        /system/fonts/NotoSansDevanagari-Regular.ttf
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f99da000-7007f99e1000 r--p 00000000 fe:00 1555                       /system/lib64/libstatslog.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   5 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd mr mw me 
-7007f99e1000-7007f99ef000 r-xp 00007000 fe:00 1555                       /system/lib64/libstatslog.so
-Size:                 56 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  56 kB
-Pss:                  10 kB
-Shared_Clean:         56 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           56 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd ex mr mw me 
-7007f99ef000-7007f99f0000 rw-p 00015000 fe:00 1555                       /system/lib64/libstatslog.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f99f0000-7007f99f1000 r--p 00016000 fe:00 1555                       /system/lib64/libstatslog.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f99f1000-7007f99f2000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f99f2000-7007f99fa000 r--s 00000000 fe:00 73                         /system/fonts/NotoSansLao-Regular.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f99fa000-7007f9a03000 r--s 00000000 fe:00 205                        /system/fonts/NotoSansTamil-Regular.ttf
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9a03000-7007f9a13000 r--p 00000000 fe:00 1224                       /system/lib64/android.hidl.memory@1.0.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  10 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007f9a13000-7007f9a27000 r-xp 00010000 fe:00 1224                       /system/lib64/android.hidl.memory@1.0.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                  20 kB
-Shared_Clean:         80 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               20 kB
-VmFlags: rd ex mr mw me 
-7007f9a27000-7007f9a28000 rw-p 00024000 fe:00 1224                       /system/lib64/android.hidl.memory@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9a28000-7007f9a2b000 r--p 00025000 fe:00 1224                       /system/lib64/android.hidl.memory@1.0.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9a2b000-7007f9a48000 r--s 00000000 fe:00 171                        /system/fonts/NotoSansGujarati-Bold.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9a48000-7007f9a51000 r--p 00000000 fe:00 1723                       /system/lib64/libbase.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   0 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f9a51000-7007f9a5a000 r-xp 00009000 fe:00 1723                       /system/lib64/libbase.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   0 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9a5a000-7007f9a5b000 rw-p 00012000 fe:00 1723                       /system/lib64/libbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9a5b000-7007f9a5c000 r--p 00013000 fe:00 1723                       /system/lib64/libbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9a5c000-7007f9a5d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f9a5d000-7007f9a5f000 r--s 00000000 fe:00 66                         /system/fonts/NotoSansShavian-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9a5f000-7007f9a73000 r--s 00000000 fe:00 264                        /system/fonts/NotoSerifDevanagari-Bold.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9a73000-7007f9a93000 r--s 00000000 fe:00 266                        /system/fonts/NotoSerifEthiopic-Bold.otf
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9a93000-7007f9a96000 r--p 00000000 fe:00 1519                       /system/lib64/libnativeloader.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f9a96000-7007f9a9a000 r-xp 00003000 fe:00 1519                       /system/lib64/libnativeloader.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9a9a000-7007f9a9b000 rw-p 00007000 fe:00 1519                       /system/lib64/libnativeloader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9a9b000-7007f9a9c000 r--p 00008000 fe:00 1519                       /system/lib64/libnativeloader.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9a9c000-7007f9a9d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f9a9d000-7007f9aa0000 r--s 00000000 fe:00 136                        /system/fonts/NotoSansRunic-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9aa0000-7007f9aa8000 r--s 00000000 fe:00 143                        /system/fonts/NotoSansGurmukhiUI-Bold.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9aa8000-7007f9abc000 r--s 00000000 fe:00 260                        /system/fonts/NotoSerifDevanagari-Regular.ttf
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9abc000-7007f9ad8000 r--s 00000000 fe:00 215                        /system/fonts/NotoSerifEthiopic-Regular.otf
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9ad8000-7007f9b30000 r--p 00000000 fe:00 1656                       /system/lib64/libc++.so
-Size:                352 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 224 kB
-Pss:                   3 kB
-Shared_Clean:        224 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          224 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007f9b30000-7007f9ba4000 r-xp 00058000 fe:00 1656                       /system/lib64/libc++.so
-Size:                464 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 388 kB
-Pss:                   6 kB
-Shared_Clean:        388 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          388 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-7007f9ba4000-7007f9ba5000 rw-p 000cc000 fe:00 1656                       /system/lib64/libc++.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9ba5000-7007f9bad000 r--p 000cd000 fe:00 1656                       /system/lib64/libc++.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         32 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f9bad000-7007f9bb1000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           16 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-7007f9bb1000-7007f9bb3000 r--s 00000000 fe:00 146                        /system/fonts/NotoSansRejang-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9bb3000-7007f9bf0000 r--s 00000000 fe:00 113                        /system/fonts/NotoSerif-Bold.ttf
-Size:                244 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9bf0000-7007f9bf1000 r--p 00000000 fe:00 1614                       /system/lib64/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f9bf1000-7007f9bf2000 r-xp 00001000 fe:00 1614                       /system/lib64/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9bf2000-7007f9bf3000 rw-p 00002000 fe:00 1614                       /system/lib64/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9bf3000-7007f9bf4000 r--p 00003000 fe:00 1614                       /system/lib64/libhardware.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9bf4000-7007f9bfc000 r--s 00000000 fe:00 97                         /system/fonts/NotoSansGurmukhiUI-Regular.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9bfc000-7007f9c04000 r--s 00000000 fe:00 250                        /system/fonts/NotoSerifGurmukhi-Bold.otf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9c04000-7007f9c26000 r--p 00000000 fe:00 1714                       /system/lib64/libartbase.so
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 108 kB
-Pss:                   7 kB
-Shared_Clean:        108 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          108 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007f9c26000-7007f9c72000 r-xp 00022000 fe:00 1714                       /system/lib64/libartbase.so
-Size:                304 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 164 kB
-Pss:                   7 kB
-Shared_Clean:        164 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          164 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd ex mr mw me 
-7007f9c72000-7007f9c73000 rw-p 0006e000 fe:00 1714                       /system/lib64/libartbase.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9c73000-7007f9c75000 r--p 0006f000 fe:00 1714                       /system/lib64/libartbase.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9c75000-7007f9c7c000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007f9c7c000-7007f9c84000 r--s 00000000 fe:00 78                         /system/fonts/NotoSansGurmukhi-Bold.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9c84000-7007f9ca8000 r--s 00000000 fe:00 218                        /system/fonts/NotoSansEthiopic-Bold.ttf
-Size:                144 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9ca8000-7007f9caa000 r--p 00000000 fe:00 1258                       /system/lib64/libdexfile_external.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f9caa000-7007f9cad000 r-xp 00002000 fe:00 1258                       /system/lib64/libdexfile_external.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9cad000-7007f9cae000 rw-p 00005000 fe:00 1258                       /system/lib64/libdexfile_external.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9cae000-7007f9caf000 r--p 00006000 fe:00 1258                       /system/lib64/libdexfile_external.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9caf000-7007f9cb0000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9cb0000-7007f9cb7000 r--s 00000000 fe:00 179                        /system/fonts/NotoSerifGurmukhi-Regular.otf
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9cb7000-7007f9cda000 r--s 00000000 fe:00 77                         /system/fonts/NotoSansEthiopic-Regular.ttf
-Size:                140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9cda000-7007f9ce3000 r--p 00000000 fe:00 1571                       /system/lib64/libtinyxml2.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   7 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007f9ce3000-7007f9cef000 r-xp 00009000 fe:00 1571                       /system/lib64/libtinyxml2.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  24 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd ex mr mw me 
-7007f9cef000-7007f9cf0000 rw-p 00015000 fe:00 1571                       /system/lib64/libtinyxml2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9cf0000-7007f9cf1000 r--p 00016000 fe:00 1571                       /system/lib64/libtinyxml2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9cf1000-7007f9cf2000 r--s 00000000 fe:00 974                        /system/usr/hyphen-data/hyph-ta.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9cf2000-7007f9cf6000 r--s 00000000 fe:00 247                        /system/fonts/NotoSansBatak-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9cf6000-7007f9d14000 r--s 00000000 fe:00 253                        /system/fonts/NotoNaskhArabicUI-Bold.ttf
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9d14000-7007f9d16000 r--p 00000000 fe:00 1256                       /system/lib64/libusbhost.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   2 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007f9d16000-7007f9d18000 r-xp 00002000 fe:00 1256                       /system/lib64/libusbhost.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9d18000-7007f9d19000 rw-p 00004000 fe:00 1256                       /system/lib64/libusbhost.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9d19000-7007f9d1a000 r--p 00005000 fe:00 1256                       /system/lib64/libusbhost.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9d1a000-7007f9d1e000 r--s 00000000 fe:00 240                        /system/fonts/NotoSansAhom-Regular.otf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9d1e000-7007f9d26000 r--s 00000000 fe:00 224                        /system/fonts/NotoSansGurmukhi-Regular.ttf
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9d26000-7007f9d63000 r--s 00000000 fe:00 91                         /system/fonts/NotoSerif-Regular.ttf
-Size:                244 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9d63000-7007f9dae000 r--p 00000000 fe:00 1681                       /system/lib64/libdng_sdk.so
-Size:                300 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 116 kB
-Pss:                  33 kB
-Shared_Clean:        116 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          116 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               33 kB
-VmFlags: rd mr mw me 
-7007f9dae000-7007f9e37000 r-xp 0004b000 fe:00 1681                       /system/lib64/libdng_sdk.so
-Size:                548 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9e37000-7007f9e38000 rw-p 000d4000 fe:00 1681                       /system/lib64/libdng_sdk.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9e38000-7007f9e3e000 r--p 000d5000 fe:00 1681                       /system/lib64/libdng_sdk.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            24 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007f9e3e000-7007f9e3f000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9e3f000-7007f9e40000 r--s 00000000 fe:00 1016                       /system/usr/hyphen-data/hyph-pt.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9e40000-7007f9e50000 r--s 00000000 fe:00 152                        /system/fonts/NotoSerifGujarati-Bold.ttf
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9e50000-7007f9e82000 r--p 00000000 fe:00 1221                       /system/lib64/libcamera_client.so
-Size:                200 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  10 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007f9e82000-7007f9ea4000 r-xp 00032000 fe:00 1221                       /system/lib64/libcamera_client.so
-Size:                136 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9ea4000-7007f9ea5000 rw-p 00054000 fe:00 1221                       /system/lib64/libcamera_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9ea5000-7007f9eb1000 r--p 00055000 fe:00 1221                       /system/lib64/libcamera_client.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         48 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            48 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me ac 
-7007f9eb1000-7007f9eb2000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9eb2000-7007f9eb3000 r--s 00000000 fe:00 1002                       /system/usr/hyphen-data/hyph-pa.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9eb3000-7007f9ec3000 r--s 00000000 fe:00 238                        /system/fonts/NotoSerifGujarati-Regular.ttf
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9ec3000-7007f9ed6000 r--p 00000000 fe:00 1528                       /system/lib64/libGLESv2.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   7 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd mr mw me 
-7007f9ed6000-7007f9edd000 r-xp 00013000 fe:00 1528                       /system/lib64/libGLESv2.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   7 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd ex mr mw me 
-7007f9edd000-7007f9ede000 rw-p 0001a000 fe:00 1528                       /system/lib64/libGLESv2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9ede000-7007f9edf000 r--p 0001b000 fe:00 1528                       /system/lib64/libGLESv2.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9edf000-7007f9ee0000 r--s 00000000 fe:00 975                        /system/usr/hyphen-data/hyph-or.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9ee0000-7007f9efe000 r--s 00000000 fe:00 63                         /system/fonts/NotoNaskhArabicUI-Regular.ttf
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9efe000-7007f9f1b000 r--s 00000000 fe:00 202                        /system/fonts/NotoNaskhArabic-Bold.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f1b000-7007f9f20000 r--p 00000000 fe:00 1104                       /system/lib64/libziparchive.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   0 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007f9f20000-7007f9f26000 r-xp 00005000 fe:00 1104                       /system/lib64/libziparchive.so
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   1 kB
-Shared_Clean:         24 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-7007f9f26000-7007f9f27000 rw-p 0000b000 fe:00 1104                       /system/lib64/libziparchive.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9f27000-7007f9f28000 r--p 0000c000 fe:00 1104                       /system/lib64/libziparchive.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9f28000-7007f9f2c000 r--s 00000000 fe:00 280                        /system/fonts/NotoSansThaana-Bold.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f2c000-7007f9f32000 r--s 00000000 fe:00 74                         /system/fonts/NotoSerifGeorgian-Bold.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f32000-7007f9f4f000 r--s 00000000 fe:00 122                        /system/fonts/NotoNaskhArabic-Regular.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f4f000-7007f9f50000 r--p 00000000 fe:00 1709                       /system/lib64/libETC1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f9f50000-7007f9f52000 r-xp 00001000 fe:00 1709                       /system/lib64/libETC1.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9f52000-7007f9f53000 rw-p 00003000 fe:00 1709                       /system/lib64/libETC1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9f53000-7007f9f54000 r--p 00004000 fe:00 1709                       /system/lib64/libETC1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9f54000-7007f9f5a000 r--s 00000000 fe:00 262                        /system/fonts/NotoSerifGeorgian-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f5a000-7007f9f5f000 r--s 00000000 fe:00 170                        /system/fonts/NotoSansGeorgian-Bold.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f5f000-7007f9f64000 r--s 00000000 fe:00 290                        /system/fonts/NotoSansGeorgian-Regular.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f64000-7007f9f69000 r--s 00000000 fe:00 68                         /system/fonts/NotoSansThaiUI-Bold.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f69000-7007f9f6f000 r--s 00000000 fe:00 134                        /system/fonts/NotoSansThaiUI-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f6f000-7007f9f8c000 r--s 00000000 fe:00 222                        /system/fonts/DancingScript-Bold.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f8c000-7007f9f8d000 r--p 00000000 fe:00 1663                       /system/lib64/libstagefright_http_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007f9f8d000-7007f9f8f000 r-xp 00001000 fe:00 1663                       /system/lib64/libstagefright_http_support.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007f9f8f000-7007f9f90000 rw-p 00003000 fe:00 1663                       /system/lib64/libstagefright_http_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007f9f90000-7007f9f91000 r--p 00004000 fe:00 1663                       /system/lib64/libstagefright_http_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007f9f91000-7007f9f92000 r--s 00000000 fe:00 1031                       /system/usr/hyphen-data/hyph-mr.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f92000-7007f9f94000 r--s 00000000 fe:00 123                        /system/fonts/NotoSansPhoenician-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9f94000-7007f9fb1000 r--s 00000000 fe:00 103                        /system/fonts/DancingScript-Regular.ttf
-Size:                116 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9fb1000-7007f9fcc000 r--s 00000000 fe:00 135                        /system/fonts/DroidSansMono.ttf
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007f9fcc000-7007f9fe7000 r--p 00000000 fe:00 1230                       /system/lib64/libdexfile.so
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                   4 kB
-Shared_Clean:         80 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           80 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007f9fe7000-7007fa014000 r-xp 0001b000 fe:00 1230                       /system/lib64/libdexfile.so
-Size:                180 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 176 kB
-Pss:                   9 kB
-Shared_Clean:        176 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          176 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd ex mr mw me 
-7007fa014000-7007fa015000 rw-p 00048000 fe:00 1230                       /system/lib64/libdexfile.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa015000-7007fa017000 r--p 00049000 fe:00 1230                       /system/lib64/libdexfile.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa017000-7007fa01b000 r--s 00000000 fe:00 263                        /system/fonts/NotoSansThaana-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa01b000-7007fa03b000 r--s 00000000 00:13 6728                       /dev/__properties__/u:object_r:persist_debug_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr me ms 
-7007fa03b000-7007fa075000 r--s 00000000 07:08 18                         /apex/com.android.tzdata/etc/icu/icu_tzdata.dat
-Size:                232 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 204 kB
-Pss:                  24 kB
-Shared_Clean:        204 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          204 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               24 kB
-VmFlags: rd mr me ms 
-7007fa075000-7007fa077000 r--p 00000000 fe:00 1575                       /system/lib64/libspeexresampler.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa077000-7007fa07a000 r-xp 00002000 fe:00 1575                       /system/lib64/libspeexresampler.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa07a000-7007fa07b000 rw-p 00005000 fe:00 1575                       /system/lib64/libspeexresampler.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa07b000-7007fa07c000 r--p 00006000 fe:00 1575                       /system/lib64/libspeexresampler.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa07c000-7007fa081000 r--s 00000000 fe:00 249                        /system/fonts/NotoSerifThai-Bold.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa081000-7007fa09f000 r--s 001db000 fe:00 3224                       /system/framework/ext.jar
-Size:                120 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa09f000-7007fa0a7000 r--p 00000000 fe:00 1624                       /system/lib64/libz.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   1 kB
-Shared_Clean:         32 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           32 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007fa0a7000-7007fa0b7000 r-xp 00008000 fe:00 1624                       /system/lib64/libz.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   5 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                5 kB
-VmFlags: rd ex mr mw me 
-7007fa0b7000-7007fa0b8000 rw-p 00018000 fe:00 1624                       /system/lib64/libz.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa0b8000-7007fa0b9000 r--p 00019000 fe:00 1624                       /system/lib64/libz.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa0b9000-7007fa0ba000 r--s 00000000 fe:00 1015                       /system/usr/hyphen-data/hyph-ml.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0ba000-7007fa0bf000 r--s 00000000 fe:00 278                        /system/fonts/NotoSerifThai-Regular.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0bf000-7007fa0c4000 r--s 00000000 fe:00 243                        /system/fonts/NotoSansThai-Bold.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0c4000-7007fa0ca000 r--s 00000000 fe:00 128                        /system/fonts/NotoSansThai-Regular.ttf
-Size:                 24 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0ca000-7007fa0cf000 r--s 00000000 fe:00 279                        /system/fonts/NotoSerifHebrew-Bold.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0cf000-7007fa0ef000 r--s 00000000 00:13 6707                       /dev/__properties__/u:object_r:exported2_default_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0ef000-7007fa0f0000 r--p 00000000 fe:00 1574                       /system/lib64/libpackagelistparser.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa0f0000-7007fa0f1000 r-xp 00001000 fe:00 1574                       /system/lib64/libpackagelistparser.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa0f1000-7007fa0f2000 rw-p 00002000 fe:00 1574                       /system/lib64/libpackagelistparser.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa0f2000-7007fa0f3000 r--p 00003000 fe:00 1574                       /system/lib64/libpackagelistparser.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa0f3000-7007fa0f6000 r--s 00000000 fe:00 207                        /system/fonts/NotoSansOsage-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa0f6000-7007fa100000 r--s 00000000 fe:00 164                        /system/fonts/CarroisGothicSC-Regular.ttf
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa100000-7007fa101000 r--p 00000000 fe:00 1120                       /system/lib64/android.hardware.media@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa101000-7007fa102000 r-xp 00001000 fe:00 1120                       /system/lib64/android.hardware.media@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa102000-7007fa103000 rw-p 00002000 fe:00 1120                       /system/lib64/android.hardware.media@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa103000-7007fa104000 r--p 00003000 fe:00 1120                       /system/lib64/android.hardware.media@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa104000-7007fa108000 r--s 00000000 fe:00 167                        /system/fonts/NotoSerifArmenian-Bold.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa108000-7007fa10d000 r--s 00000000 fe:00 223                        /system/fonts/NotoSerifHebrew-Regular.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa10d000-7007fa147000 r--s 00000000 07:08 18                         /apex/com.android.tzdata/etc/icu/icu_tzdata.dat
-Size:                232 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   2 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr me ms rr 
-7007fa147000-7007fa18a000 r--p 00000000 fe:00 1222                       /system/lib64/libsonivox.so
-Size:                268 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  10 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007fa18a000-7007fa19f000 r-xp 00043000 fe:00 1222                       /system/lib64/libsonivox.so
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa19f000-7007fa1a0000 rw-p 00058000 fe:00 1222                       /system/lib64/libsonivox.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa1a0000-7007fa1a1000 r--p 00059000 fe:00 1222                       /system/lib64/libsonivox.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa1a1000-7007fa1a9000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa1a9000-7007fa1ad000 r--s 00000000 fe:00 148                        /system/fonts/NotoSerifArmenian-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa1ad000-7007fa1b2000 r--s 00000000 fe:00 138                        /system/fonts/NotoSansHebrew-Bold.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa1b2000-7007fa1d2000 r--s 00000000 00:13 6732                       /dev/__properties__/u:object_r:radio_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa1d2000-7007fa1d3000 r--p 00000000 fe:00 1629                       /system/lib64/libdexfile_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa1d3000-7007fa1d4000 r-xp 00001000 fe:00 1629                       /system/lib64/libdexfile_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa1d4000-7007fa1d5000 rw-p 00002000 fe:00 1629                       /system/lib64/libdexfile_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa1d5000-7007fa1d6000 r--p 00003000 fe:00 1629                       /system/lib64/libdexfile_support.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa1d6000-7007fa1da000 r--s 00000000 fe:00 104                        /system/fonts/NotoSansArmenian-Bold.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa1da000-7007fa1df000 r--s 00000000 fe:00 158                        /system/fonts/NotoSansHebrew-Regular.ttf
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa1df000-7007fa1ee000 r--s 00000000 fe:00 192                        /system/fonts/ComingSoon.ttf
-Size:                 60 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa1ee000-7007fa20e000 rw-p 00000000 00:00 0                          [anon:dalvik-LinearAlloc]
-Name:           [anon:dalvik-LinearAlloc]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  80 kB
-Pss:                  76 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:        76 kB
-Referenced:           76 kB
-Anonymous:            80 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               76 kB
-VmFlags: rd wr mr mw me ac 
-7007fa20e000-7007fa21e000 r--p 00000000 fe:00 1535                       /system/lib64/libmemunreachable.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  56 kB
-Pss:                   9 kB
-Shared_Clean:         56 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           56 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007fa21e000-7007fa239000 r-xp 00010000 fe:00 1535                       /system/lib64/libmemunreachable.so
-Size:                108 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 100 kB
-Pss:                  21 kB
-Shared_Clean:        100 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          100 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               21 kB
-VmFlags: rd ex mr mw me 
-7007fa239000-7007fa23a000 rw-p 0002b000 fe:00 1535                       /system/lib64/libmemunreachable.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa23a000-7007fa23c000 r--p 0002c000 fe:00 1535                       /system/lib64/libmemunreachable.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa23c000-7007fa23d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa23d000-7007fa24e000 r--s 00000000 fe:00 200                        /system/fonts/CutiveMono.ttf
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa24e000-7007fa255000 r--p 00000000 fe:00 1174                       /system/lib64/libmediaextractor.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   4 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007fa255000-7007fa25c000 r-xp 00007000 fe:00 1174                       /system/lib64/libmediaextractor.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   9 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd ex mr mw me 
-7007fa25c000-7007fa25d000 rw-p 0000e000 fe:00 1174                       /system/lib64/libmediaextractor.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa25d000-7007fa25e000 r--p 0000f000 fe:00 1174                       /system/lib64/libmediaextractor.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa25e000-7007fa25f000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa25f000-7007fa263000 r--s 00000000 fe:00 255                        /system/fonts/NotoSansArmenian-Regular.ttf
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa263000-7007fa264000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa264000-7007fa267000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa267000-7007fa268000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa269000-7007fa26b000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa26b000-7007fa26c000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa26c000-7007fa26f000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa26f000-7007fa270000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa270000-7007fa271000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007fa271000-7007fa279000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa279000-7007fa27a000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa27a000-7007fa27d000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa27d000-7007fa27e000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa27e000-7007fa27f000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007fa27f000-7007fa287000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa287000-7007fa292000 r--p 00000000 fe:00 1524                       /system/lib64/android.hardware.graphics.allocator@2.0.so
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   4 kB
-Shared_Clean:         44 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           44 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007fa292000-7007fa29c000 r-xp 0000b000 fe:00 1524                       /system/lib64/android.hardware.graphics.allocator@2.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa29c000-7007fa29d000 rw-p 00015000 fe:00 1524                       /system/lib64/android.hardware.graphics.allocator@2.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa29d000-7007fa29f000 r--p 00016000 fe:00 1524                       /system/lib64/android.hardware.graphics.allocator@2.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa29f000-7007fa2a0000 r--s 00000000 fe:00 995                        /system/usr/hyphen-data/hyph-la.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa2a0000-7007fa2a1000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2a1000-7007fa2a3000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2a4000-7007fa2a6000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2a6000-7007fa2a7000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa2a7000-7007fa2aa000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2aa000-7007fa2ab000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa2ab000-7007fa2ac000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007fa2ac000-7007fa2b4000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2b4000-7007fa2b5000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa2b5000-7007fa2b8000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2b8000-7007fa2b9000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fa2b9000-7007fa2ba000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007fa2ba000-7007fa2c2000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2c2000-7007fa2ee000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                176 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2ee000-7007fa2f2000 r--p 00000000 fe:00 1525                       /system/lib64/libheif.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   4 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007fa2f2000-7007fa2f4000 r-xp 00004000 fe:00 1525                       /system/lib64/libheif.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa2f4000-7007fa2f5000 rw-p 00006000 fe:00 1525                       /system/lib64/libheif.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa2f5000-7007fa2f6000 r--p 00007000 fe:00 1525                       /system/lib64/libheif.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa2f6000-7007fa2f7000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fa2f7000-7007fa317000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa317000-7007fa32a000 r--p 00000000 fe:00 1186                       /system/lib64/libhwbinder.so
-Size:                 76 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   2 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007fa32a000-7007fa33b000 r-xp 00013000 fe:00 1186                       /system/lib64/libhwbinder.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                   2 kB
-Shared_Clean:         68 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           68 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd ex mr mw me 
-7007fa33b000-7007fa33c000 rw-p 00024000 fe:00 1186                       /system/lib64/libhwbinder.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa33c000-7007fa33e000 r--p 00025000 fe:00 1186                       /system/lib64/libhwbinder.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa33e000-7007fa33f000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa33f000-7007fa340000 r--s 00000000 fe:00 968                        /system/usr/hyphen-data/hyph-kn.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa340000-7007fa348000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa348000-7007fa36b000 r--p 00000000 fe:00 1698                       /system/lib64/libunwindstack.so
-Size:                140 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   6 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007fa36b000-7007fa39c000 r-xp 00023000 fe:00 1698                       /system/lib64/libunwindstack.so
-Size:                196 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa39c000-7007fa39d000 rw-p 00054000 fe:00 1698                       /system/lib64/libunwindstack.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa39d000-7007fa3a4000 r--p 00055000 fe:00 1698                       /system/lib64/libunwindstack.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         28 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            28 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007fa3a4000-7007fa3a5000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa3a5000-7007fa3a6000 r--s 00000000 fe:00 999                        /system/usr/hyphen-data/hyph-hy.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa3a6000-7007fa3e2000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa3e2000-7007fa3e4000 r--p 00000000 fe:00 1236                       /system/lib64/libaudiomanager.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   1 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007fa3e4000-7007fa3e5000 r-xp 00002000 fe:00 1236                       /system/lib64/libaudiomanager.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa3e5000-7007fa3e6000 rw-p 00003000 fe:00 1236                       /system/lib64/libaudiomanager.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa3e6000-7007fa3e7000 r--p 00004000 fe:00 1236                       /system/lib64/libaudiomanager.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa3e7000-7007fa3e8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa3e8000-7007fa420000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                224 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa420000-7007fa42d000 r--p 00000000 fe:00 1241                       /system/lib64/libsensor.so
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  10 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007fa42d000-7007fa434000 r-xp 0000d000 fe:00 1241                       /system/lib64/libsensor.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   9 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd ex mr mw me 
-7007fa434000-7007fa435000 rw-p 00014000 fe:00 1241                       /system/lib64/libsensor.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa435000-7007fa438000 r--p 00015000 fe:00 1241                       /system/lib64/libsensor.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa438000-7007fa439000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa439000-7007fa43b000 r--s 00000000 fe:00 82                         /system/fonts/NotoSansOsmanya-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa43b000-7007fa477000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa477000-7007fa478000 r--p 00000000 fe:00 1182                       /system/lib64/libgraphicsenv.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa478000-7007fa479000 r-xp 00001000 fe:00 1182                       /system/lib64/libgraphicsenv.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa479000-7007fa47a000 rw-p 00002000 fe:00 1182                       /system/lib64/libgraphicsenv.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa47a000-7007fa47b000 r--p 00003000 fe:00 1182                       /system/lib64/libgraphicsenv.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa47b000-7007fa47c000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd wr mr mw me ac 
-7007fa47c000-7007fa47d000 r--s 00000000 fe:00 993                        /system/usr/hyphen-data/hyph-hr.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa47d000-7007fa485000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa485000-7007fa48c000 r--p 00000000 fe:00 1132                       /system/lib64/liblog.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   0 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa48c000-7007fa49d000 r-xp 00007000 fe:00 1132                       /system/lib64/liblog.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                   1 kB
-Shared_Clean:         68 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           68 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd ex mr mw me 
-7007fa49d000-7007fa49e000 rw-p 00018000 fe:00 1132                       /system/lib64/liblog.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa49e000-7007fa49f000 r--p 00019000 fe:00 1132                       /system/lib64/liblog.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa49f000-7007fa4a0000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa4a0000-7007fa4d8000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                224 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa4d8000-7007fa4ec000 r--p 00000000 fe:00 1108                       /system/lib64/libdrmframework.so
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  11 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               11 kB
-VmFlags: rd mr mw me 
-7007fa4ec000-7007fa4f8000 r-xp 00014000 fe:00 1108                       /system/lib64/libdrmframework.so
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  48 kB
-Pss:                  12 kB
-Shared_Clean:         48 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd ex mr mw me 
-7007fa4f8000-7007fa4f9000 rw-p 00020000 fe:00 1108                       /system/lib64/libdrmframework.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa4f9000-7007fa4fe000 r--p 00021000 fe:00 1108                       /system/lib64/libdrmframework.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         20 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:            20 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007fa4fe000-7007fa4ff000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa4ff000-7007fa527000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa527000-7007fa540000 r--p 00000000 fe:00 1577                       /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-Size:                100 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   9 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007fa540000-7007fa568000 r-xp 00019000 fe:00 1577                       /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa568000-7007fa569000 rw-p 00041000 fe:00 1577                       /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa569000-7007fa56d000 r--p 00042000 fe:00 1577                       /system/lib64/android.hardware.graphics.bufferqueue@1.0.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa56d000-7007fa56f000 r--s 00000000 fe:00 58                         /system/fonts/NotoSansOldTurkic-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa56f000-7007fa597000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa597000-7007fa59b000 r--p 00000000 fe:00 1619                       /system/lib64/libnativehelper.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   3 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007fa59b000-7007fa59e000 r-xp 00004000 fe:00 1619                       /system/lib64/libnativehelper.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa59e000-7007fa59f000 rw-p 00007000 fe:00 1619                       /system/lib64/libnativehelper.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa59f000-7007fa5a0000 r--p 00008000 fe:00 1619                       /system/lib64/libnativehelper.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa5a0000-7007fa5a1000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa5a1000-7007fa5a3000 r--s 00000000 fe:00 208                        /system/fonts/NotoSansOldSouthArabian-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa5a3000-7007fa5c3000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa5c3000-7007fa5cc000 r--p 00000000 fe:00 1181                       /system/lib64/libimg_utils.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                   9 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                9 kB
-VmFlags: rd mr mw me 
-7007fa5cc000-7007fa5d4000 r-xp 00009000 fe:00 1181                       /system/lib64/libimg_utils.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa5d4000-7007fa5d5000 rw-p 00011000 fe:00 1181                       /system/lib64/libimg_utils.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa5d5000-7007fa5d7000 r--p 00012000 fe:00 1181                       /system/lib64/libimg_utils.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa5d7000-7007fa5d8000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa5d8000-7007fa5da000 r--s 00000000 fe:00 193                        /system/fonts/NotoSansOldItalic-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa5da000-7007fa62e000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                336 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa62e000-7007fa630000 r--p 00000000 fe:00 1251                       /system/lib64/libnetd_client.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa630000-7007fa632000 r-xp 00002000 fe:00 1251                       /system/lib64/libnetd_client.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa632000-7007fa633000 rw-p 00004000 fe:00 1251                       /system/lib64/libnetd_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa633000-7007fa634000 r--p 00005000 fe:00 1251                       /system/lib64/libnetd_client.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa634000-7007fa635000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa635000-7007fa636000 r--s 00000000 fe:00 1005                       /system/usr/hyphen-data/hyph-hi.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa636000-7007fa64a000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa64a000-7007fa64b000 r--p 00000000 fe:00 1628                       /system/lib64/android.hardware.graphics.common@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fa64b000-7007fa64c000 r-xp 00001000 fe:00 1628                       /system/lib64/android.hardware.graphics.common@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa64c000-7007fa64d000 rw-p 00002000 fe:00 1628                       /system/lib64/android.hardware.graphics.common@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa64d000-7007fa64e000 r--p 00003000 fe:00 1628                       /system/lib64/android.hardware.graphics.common@1.1.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa64e000-7007fa696000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                288 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa696000-7007fa6e4000 r--p 00000000 fe:00 1194                       /system/lib64/libgui.so
-Size:                312 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 232 kB
-Pss:                  39 kB
-Shared_Clean:        232 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          232 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               39 kB
-VmFlags: rd mr mw me 
-7007fa6e4000-7007fa72c000 r-xp 0004e000 fe:00 1194                       /system/lib64/libgui.so
-Size:                288 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 288 kB
-Pss:                  49 kB
-Shared_Clean:        288 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          288 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               49 kB
-VmFlags: rd ex mr mw me 
-7007fa72c000-7007fa72d000 rw-p 00096000 fe:00 1194                       /system/lib64/libgui.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa72d000-7007fa73e000 r--p 00097000 fe:00 1194                       /system/lib64/libgui.so
-Size:                 68 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  68 kB
-Pss:                   3 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         68 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           48 kB
-Anonymous:            68 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me ac 
-7007fa73e000-7007fa73f000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa73f000-7007fa740000 r--s 00000000 fe:00 1004                       /system/usr/hyphen-data/hyph-gu.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa740000-7007fa742000 r--s 00000000 fe:00 166                        /system/fonts/NotoSansOlChiki-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa742000-7007fa74e000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa74e000-7007fa755000 r--p 00000000 fe:00 1726                       /system/lib64/libGLESv1_CM.so
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  28 kB
-Pss:                   4 kB
-Shared_Clean:         28 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           28 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me 
-7007fa755000-7007fa758000 r-xp 00007000 fe:00 1726                       /system/lib64/libGLESv1_CM.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   3 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd ex mr mw me 
-7007fa758000-7007fa759000 rw-p 0000a000 fe:00 1726                       /system/lib64/libGLESv1_CM.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa759000-7007fa75a000 r--p 0000b000 fe:00 1726                       /system/lib64/libGLESv1_CM.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa75a000-7007fa75b000 r--s 00000000 fe:00 1011                       /system/usr/hyphen-data/hyph-eu.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa75b000-7007fa75d000 r--s 00000000 fe:00 71                         /system/fonts/NotoSansOgham-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa75d000-7007fa785000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa785000-7007fa78a000 r--p 00000000 fe:00 1207                       /system/lib64/libcamera_metadata.so
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   2 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007fa78a000-7007fa78d000 r-xp 00005000 fe:00 1207                       /system/lib64/libcamera_metadata.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa78d000-7007fa78f000 rw-p 00008000 fe:00 1207                       /system/lib64/libcamera_metadata.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa78f000-7007fa790000 r--p 0000a000 fe:00 1207                       /system/lib64/libcamera_metadata.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa790000-7007fa791000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa791000-7007fa793000 r--s 00000000 fe:00 88                         /system/fonts/NotoSansLydian-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa793000-7007fa7db000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                288 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa7db000-7007fa806000 r--p 00000000 fe:00 1248                       /system/lib64/libandroidfw.so
-Size:                172 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 128 kB
-Pss:                  19 kB
-Shared_Clean:        128 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          128 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               19 kB
-VmFlags: rd mr mw me 
-7007fa806000-7007fa839000 r-xp 0002b000 fe:00 1248                       /system/lib64/libandroidfw.so
-Size:                204 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 200 kB
-Pss:                  11 kB
-Shared_Clean:        200 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          200 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               11 kB
-VmFlags: rd ex mr mw me 
-7007fa839000-7007fa83a000 rw-p 0005e000 fe:00 1248                       /system/lib64/libandroidfw.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa83a000-7007fa83c000 r--p 0005f000 fe:00 1248                       /system/lib64/libandroidfw.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa83c000-7007fa83d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa83d000-7007fa83e000 r--s 00000000 fe:00 1027                       /system/usr/hyphen-data/hyph-bn.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa83e000-7007fa840000 r--s 00000000 fe:00 87                         /system/fonts/NotoSansLycian-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa840000-7007fa85c000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa85c000-7007fa88b000 r--p 00000000 fe:00 1556                       /system/lib64/android.hardware.media.omx@1.0.so
-Size:                188 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 124 kB
-Pss:                  23 kB
-Shared_Clean:        124 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          124 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               23 kB
-VmFlags: rd mr mw me 
-7007fa88b000-7007fa8dd000 r-xp 0002f000 fe:00 1556                       /system/lib64/android.hardware.media.omx@1.0.so
-Size:                328 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 292 kB
-Pss:                  60 kB
-Shared_Clean:        292 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          292 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               60 kB
-VmFlags: rd ex mr mw me 
-7007fa8dd000-7007fa8de000 rw-p 00081000 fe:00 1556                       /system/lib64/android.hardware.media.omx@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa8de000-7007fa8e6000 r--p 00082000 fe:00 1556                       /system/lib64/android.hardware.media.omx@1.0.so
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  32 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         32 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:            32 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me ac 
-7007fa8e6000-7007fa8e9000 r--s 00000000 fe:00 216                        /system/fonts/NotoSansLimbu-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa8e9000-7007fa919000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa919000-7007fa92b000 r--p 00000000 fe:00 1466                       /system/lib64/libui.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   6 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd mr mw me 
-7007fa92b000-7007fa93d000 r-xp 00012000 fe:00 1466                       /system/lib64/libui.so
-Size:                 72 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                   6 kB
-Shared_Clean:         52 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           52 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                6 kB
-VmFlags: rd ex mr mw me 
-7007fa93d000-7007fa93e000 rw-p 00024000 fe:00 1466                       /system/lib64/libui.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa93e000-7007fa93f000 r--p 00025000 fe:00 1466                       /system/lib64/libui.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa93f000-7007fa940000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fa940000-7007fa94a000 r--p 00000000 fe:00 1667                       /system/lib64/android.hardware.memtrack@1.0.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                  10 kB
-Shared_Clean:         40 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               10 kB
-VmFlags: rd mr mw me 
-7007fa94a000-7007fa953000 r-xp 0000a000 fe:00 1667                       /system/lib64/android.hardware.memtrack@1.0.so
-Size:                 36 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  36 kB
-Pss:                  18 kB
-Shared_Clean:         36 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           36 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               18 kB
-VmFlags: rd ex mr mw me 
-7007fa953000-7007fa954000 rw-p 00013000 fe:00 1667                       /system/lib64/android.hardware.memtrack@1.0.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa954000-7007fa956000 r--p 00014000 fe:00 1667                       /system/lib64/android.hardware.memtrack@1.0.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa956000-7007fa958000 r--s 00000000 fe:00 81                         /system/fonts/NotoSansLisu-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa958000-7007fa9a0000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                288 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa9a0000-7007fa9aa000 r--p 00000000 fe:00 1654                       /system/lib64/libbacktrace.so
-Size:                 40 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                   3 kB
-Shared_Clean:         40 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           40 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007fa9aa000-7007fa9ba000 r-xp 0000a000 fe:00 1654                       /system/lib64/libbacktrace.so
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa9ba000-7007fa9bb000 rw-p 0001a000 fe:00 1654                       /system/lib64/libbacktrace.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa9bb000-7007fa9bc000 r--p 0001b000 fe:00 1654                       /system/lib64/libbacktrace.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa9bc000-7007fa9bd000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa9bd000-7007fa9d9000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa9d9000-7007fa9dd000 r--p 00000000 fe:00 1637                       /system/lib64/libbpf.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   3 kB
-Shared_Clean:         16 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           16 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007fa9dd000-7007fa9e1000 r-xp 00004000 fe:00 1637                       /system/lib64/libbpf.so
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007fa9e1000-7007fa9e2000 rw-p 00008000 fe:00 1637                       /system/lib64/libbpf.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fa9e2000-7007fa9e3000 r--p 00009000 fe:00 1637                       /system/lib64/libbpf.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fa9e3000-7007fa9e4000 r--s 00000000 fe:00 966                        /system/usr/hyphen-data/hyph-bg.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa9e4000-7007fa9e6000 r--s 00000000 fe:00 151                        /system/fonts/NotoSansKayahLi-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fa9e6000-7007faa16000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faa16000-7007faa18000 r--p 00000000 fe:00 1465                       /system/lib64/libbinderthreadstate.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007faa18000-7007faa1a000 r-xp 00002000 fe:00 1465                       /system/lib64/libbinderthreadstate.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   0 kB
-Shared_Clean:          8 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            8 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007faa1a000-7007faa1b000 rw-p 00004000 fe:00 1465                       /system/lib64/libbinderthreadstate.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faa1b000-7007faa1c000 r--p 00005000 fe:00 1465                       /system/lib64/libbinderthreadstate.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007faa1c000-7007faa1d000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007faa1d000-7007faa59000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                240 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faa59000-7007faa5c000 r--p 00000000 fe:00 1155                       /system/lib64/libutilscallstack.so
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   1 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007faa5c000-7007faa5e000 r-xp 00003000 fe:00 1155                       /system/lib64/libutilscallstack.so
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007faa5e000-7007faa5f000 rw-p 00005000 fe:00 1155                       /system/lib64/libutilscallstack.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faa5f000-7007faa60000 r--p 00006000 fe:00 1155                       /system/lib64/libutilscallstack.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007faa60000-7007faa61000 r--s 00000000 fe:00 990                        /system/usr/hyphen-data/hyph-as.hyb
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faa61000-7007faa63000 r--s 00000000 fe:00 172                        /system/fonts/NotoSansInscriptionalParthian-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faa63000-7007faa97000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                208 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faa97000-7007faaad000 r--p 00000000 fe:00 1540                       /system/lib64/libRScpp.so
-Size:                 88 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                  12 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd mr mw me 
-7007faaad000-7007faadb000 r-xp 00016000 fe:00 1540                       /system/lib64/libRScpp.so
-Size:                184 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me 
-7007faadb000-7007faadc000 rw-p 00044000 fe:00 1540                       /system/lib64/libRScpp.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faadc000-7007faadd000 r--p 00045000 fe:00 1540                       /system/lib64/libRScpp.so
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007faadd000-7007faade000 rw-p 00000000 00:00 0                          [anon:.bss]
-Name:           [anon:.bss]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faade000-7007faaf2000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faaf2000-7007fab32000 rw-p 00000000 00:00 0 
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fab32000-7007fab33000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fab33000-7007fab36000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-7007fab36000-7007fab37000 r--s 00046000 fe:00 1943                       /system/priv-app/SettingsProvider/SettingsProvider.apk
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         4 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr me ms 
-7007fab37000-7007fab38000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fab38000-7007fab3a000 r--s 00000000 fe:00 286                        /system/fonts/NotoSansInscriptionalPahlavi-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fab3a000-7007fab52000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fab52000-7007fab53000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fab53000-7007fab54000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fab54000-7007fab55000 rw-p 00000000 00:00 0                          [anon:linker_alloc_lob]
-Name:           [anon:linker_alloc_lob]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fab55000-7007fab61000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fab61000-7007fab62000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fab62000-7007fab65000 r--s 00000000 fe:00 149                        /system/fonts/NotoSansElbasan-Regular.otf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fab65000-7007fab8d000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fab8d000-7007fab8f000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fab8f000-7007fab93000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fab93000-7007fab94000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fab94000-7007fab95000 r--s 00000000 fe:30 18                         /vendor/overlay/framework-res__auto_generated_rro.apk
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fab95000-7007fab99000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fab99000-7007fab9a000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fab9a000-7007fab9b000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fab9b000-7007fab9c000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fab9c000-7007fab9d000 r--s 00004000 fe:30 18                         /vendor/overlay/framework-res__auto_generated_rro.apk
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fab9d000-7007fabad000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fabad000-7007fabae000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fabae000-7007fabd6000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                160 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fabd6000-7007fabd7000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fabd7000-7007fabda000 r--s 00000000 fe:00 229                        /system/fonts/NotoSansDeseret-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fabda000-7007fabee000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fabee000-7007fabef000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fabef000-7007fabf1000 r--s 00000000 fe:00 189                        /system/fonts/NotoSansImperialAramaic-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fabf1000-7007fabfd000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fabfd000-7007fabfe000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fabfe000-7007fabff000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fabff000-7007fac37000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                224 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fac37000-7007fac39000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fac39000-7007fac3b000 r--s 00000000 fe:00 265                        /system/fonts/NotoSansHanunoo-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fac3b000-7007fac57000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fac57000-7007fac58000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fac58000-7007fac5a000 r--s 00000000 fe:00 98                         /system/fonts/NotoSansGothic-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fac5a000-7007fac8e000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                208 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fac8e000-7007fac8f000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fac8f000-7007fac91000 r--s 00000000 fe:00 114                        /system/fonts/NotoSansCypriot-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fac91000-7007faca1000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faca1000-7007faca2000 r--p 00000000 00:00 0                          [anon:atexit handlers]
-Name:           [anon:atexit handlers]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007faca2000-7007faca3000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007faca3000-7007faca4000 r--s 00000000 fe:10 237571                     /data/resource-cache/vendor@overlay@framework-res__auto_generated_rro.apk@idmap
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faca4000-7007faca6000 r--s 00000000 fe:00 61                         /system/fonts/NotoSansCarian-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faca6000-7007facb6000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007facb6000-7007facb7000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007facb7000-7007facc7000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007facc7000-7007facc8000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007facc8000-7007facca000 r--s 00000000 fe:00 102                        /system/fonts/NotoSansBuhid-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007facca000-7007facce000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007facce000-7007faccf000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007faccf000-7007face3000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007face3000-7007face4000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007face4000-7007face6000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007face6000-7007face8000 r--s 00000000 fe:00 155                        /system/fonts/NotoSansBuginese-Regular.ttf
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007face8000-7007fad3c000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                336 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fad3c000-7007fad3d000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fad3d000-7007fad6d000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fad6d000-7007fad6e000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fad6e000-7007fad8a000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fad8a000-7007fad8b000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fad8b000-7007fad8c000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fad8c000-7007fada8000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fada8000-7007fada9000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fada9000-7007fadac000 r--s 00000000 fe:00 276                        /system/fonts/NotoSansAvestan-Regular.ttf
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fadac000-7007fadc0000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fadc0000-7007fadc1000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fadc1000-7007fadd1000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fadd1000-7007fadd2000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fadd2000-7007fadd3000 r--s 00000000 fe:00 3210                       /system/framework/android.test.base.impl.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fadd3000-7007fade7000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fade7000-7007fade8000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fade8000-7007fade9000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fade9000-7007fadea000 r--s 00000000 fe:00 3394                       /system/framework/framework-oahl-backward-compatibility.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fadea000-7007fae22000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                224 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae22000-7007fae23000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae23000-7007fae24000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fae24000-7007fae3c000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae3c000-7007fae3d000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fae3d000-7007fae3e000 r--s 00000000 fe:00 3144                       /system/framework/ims-common.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fae3e000-7007fae3f000 r--s 00000000 fe:00 3155                       /system/framework/voip-common.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fae3f000-7007fae43000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae43000-7007fae44000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fae44000-7007fae45000 r--s 00000000 fe:00 3395                       /system/framework/telephony-common.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fae45000-7007fae46000 r--s 00000000 fe:00 3158                       /system/framework/framework.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fae46000-7007fae47000 r--s 00004000 fe:00 3208                       /system/framework/apache-xml.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fae47000-7007fae4b000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae4b000-7007fae4c000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae4c000-7007fae7c000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                192 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fae7c000-7007faebc000 rw-p 00000000 00:00 0                          [anon:dalvik-mark stack]
-Name:           [anon:dalvik-mark stack]
-Size:                256 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faebc000-7007faebd000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007faebd000-7007faebe000 r--s 00000000 fe:00 3153                       /system/framework/bouncycastle.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faebe000-7007faeca000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faeca000-7007faecb000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faecb000-7007faecc000 r--s 00000000 fe:00 3151                       /system/framework/okhttp.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faecc000-7007faecd000 r--s 00000000 fe:00 3349                       /system/framework/conscrypt.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faecd000-7007faed5000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faed5000-7007faed6000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007faed6000-7007faeda000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faeda000-7007faefa000 rw-p 00000000 00:00 0                          [anon:dalvik-large marked objects]
-Name:           [anon:dalvik-large marked objects]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007faefa000-7007faf1a000 rw-p 00000000 00:00 0                          [anon:dalvik-large live objects]
-Name:           [anon:dalvik-large live objects]
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faf1a000-7007faf3a000 r--s 00000000 00:13 6709                       /dev/__properties__/u:object_r:fingerprint_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   1 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr me ms 
-7007faf3a000-7007faf5a000 r--s 00000000 00:13 6747                       /dev/__properties__/u:object_r:vold_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faf5a000-7007faf5b000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007faf5b000-7007faf5c000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faf5c000-7007faf78000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                112 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faf78000-7007faf98000 r--s 00000000 00:13 6678                       /dev/__properties__/u:object_r:config_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faf98000-7007faf99000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faf99000-7007faf9a000 r--s 00000000 fe:00 3157                       /system/framework/core-simple.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faf9a000-7007faf9c000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faf9c000-7007fafb0000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fafb0000-7007fafb1000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fafb1000-7007fafb3000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fafb3000-7007fafb7000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fafb7000-7007fafd7000 r--s 00000000 00:13 6696                       /dev/__properties__/u:object_r:dalvik_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fafd7000-7007fafd8000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fafd8000-7007fafd9000 r--s 00004000 fe:00 3162                       /system/framework/core-libart.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fafd9000-7007fafdb000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fafdb000-7007fafe7000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fafe7000-7007fafe8000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fafe8000-7007faff8000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faff8000-7007faff9000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faff9000-7007faffa000 r--s 00007000 fe:00 3215                       /system/framework/core-oj.jar
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007faffa000-7007faffc000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007faffc000-7007fb014000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 96 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb014000-7007fb034000 r--s 00000000 00:13 6740                       /dev/__properties__/u:object_r:system_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb034000-7007fb036000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007fb036000-7007fb042000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb042000-7007fb043000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb043000-7007fb044000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb044000-7007fb045000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb045000-7007fb046000 rw-p 00000000 00:00 0                          [anon:dalvik-mod union bitmap]
-Name:           [anon:dalvik-mod union bitmap]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb046000-7007fb05a000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 80 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb05a000-7007fb07a000 r--s 00000000 00:13 6717                       /dev/__properties__/u:object_r:log_tag_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb07a000-7007fb07b000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb07b000-7007fb07c000 r--p 00000000 00:00 0                          [anon:atexit handlers]
-Name:           [anon:atexit handlers]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fb07c000-7007fb07e000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb07e000-7007fb093000 r--p 00af1000 fe:00 3165                       /system/framework/x86_64/boot-framework.art
-Size:                 84 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  64 kB
-Pss:                   3 kB
-Shared_Clean:         64 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           64 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                3 kB
-VmFlags: rd mr mw me 
-7007fb093000-7007fb094000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb094000-7007fb095000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb095000-7007fb0a5000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 64 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb0a5000-7007fb0c5000 r--s 00000000 00:13 6718                       /dev/__properties__/u:object_r:logd_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb0c5000-7007fb0c6000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb0c6000-7007fb0c7000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb0c7000-7007fb0c9000 rw-p 00000000 00:00 0                          [anon:dalvik-concurrent copying sweep array free buffer]
-Name:           [anon:dalvik-concurrent copying sweep array free buffer]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb0c9000-7007fb0d5000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 48 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb0d5000-7007fb0d6000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb0d6000-7007fb0de000 rw-p 00000000 00:00 0                          [anon:dalvik-thread local mark stack]
-Name:           [anon:dalvik-thread local mark stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb0de000-7007fb0fe000 r--s 00000000 00:13 6712                       /dev/__properties__/u:object_r:heapprofd_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb0fe000-7007fb11e000 r--s 00000000 00:13 6699                       /dev/__properties__/u:object_r:default_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  24 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         24 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           24 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb11e000-7007fb11f000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb11f000-7007fb121000 rw-p 00000000 00:00 0                          [anon:dalvik-concurrent copying sweep array free buffer]
-Name:           [anon:dalvik-concurrent copying sweep array free buffer]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb121000-7007fb123000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007fb123000-7007fb124000 r--p 00006000 fe:00 3170                       /system/framework/x86_64/boot-android.test.base.impl.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb124000-7007fb125000 r--p 00002000 fe:00 3201                       /system/framework/x86_64/boot-framework-oahl-backward-compatibility.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb125000-7007fb126000 r--p 0001c000 fe:00 3176                       /system/framework/x86_64/boot-ims-common.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb126000-7007fb127000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb127000-7007fb128000 r--p 00011000 fe:00 3198                       /system/framework/x86_64/boot-voip-common.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb128000-7007fb12b000 r--p 00116000 fe:00 3178                       /system/framework/x86_64/boot-telephony-common.art
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb12b000-7007fb12c000 r--p 0004d000 fe:00 3196                       /system/framework/x86_64/boot-ext.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb12c000-7007fb12e000 r--p 00067000 fe:00 3167                       /system/framework/x86_64/boot-apache-xml.art
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb12e000-7007fb12f000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb12f000-7007fb130000 r--p 00068000 fe:00 3175                       /system/framework/x86_64/boot-bouncycastle.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb130000-7007fb131000 r--p 0003d000 fe:00 3166                       /system/framework/x86_64/boot-okhttp.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   2 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me 
-7007fb131000-7007fb132000 r--p 00040000 fe:00 3168                       /system/framework/x86_64/boot-conscrypt.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb132000-7007fb137000 r--p 002d1000 fe:00 3184                       /system/framework/x86_64/boot.art
-Size:                 20 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  20 kB
-Pss:                   1 kB
-Shared_Clean:         20 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           20 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me 
-7007fb137000-7007fb13e000 rw-p 00000000 fe:00 944                        /system/etc/event-log-tags
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb13e000-7007fb140000 rw-p 00000000 00:00 0                          [anon:dalvik-indirect ref table]
-Name:           [anon:dalvik-indirect ref table]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb140000-7007fb141000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fb141000-7007fb144000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb144000-7007fb145000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fb145000-7007fb165000 r--s 00000000 00:13 6697                       /dev/__properties__/u:object_r:debug_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb165000-7007fb166000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb166000-7007fb167000 r--p 00001000 fe:00 3197                       /system/framework/x86_64/boot-core-simple.art
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb167000-7007fb16a000 r--p 00132000 fe:00 3174                       /system/framework/x86_64/boot-core-libart.art
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:         12 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me 
-7007fb16a000-7007fb16b000 r--s 00000000 00:13 6990                       /dev/event-log-tags
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb16b000-7007fb16c000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb16c000-7007fb170000 r--p 00000000 00:00 0                          [anon:atexit handlers]
-Name:           [anon:atexit handlers]
-Size:                 16 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  16 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:            16 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fb170000-7007fb190000 r--s 00000000 00:13 6750                       /dev/__properties__/properties_serial
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb190000-7007fb191000 rw-p 00000000 00:00 0                          [anon:System property context nodes]
-Name:           [anon:System property context nodes]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb191000-7007fb194000 r--s 00000000 00:13 6672                       /dev/__properties__/property_info
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb194000-7007fb195000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb195000-7007fb196000 rw-p 00000000 00:00 0                          [anon:arc4random data]
-Name:           [anon:arc4random data]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb196000-7007fb197000 rw-p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb197000-7007fb198000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb198000-7007fb1a5000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                 52 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  52 kB
-Pss:                  36 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         16 kB
-Private_Clean:         0 kB
-Private_Dirty:        36 kB
-Referenced:           48 kB
-Anonymous:            52 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               36 kB
-VmFlags: rd wr mr mw me ac 
-7007fb1a5000-7007fb1c5000 r--s 00000000 00:13 6699                       /dev/__properties__/u:object_r:default_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb1c5000-7007fb1c7000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd mr mw me ac 
-7007fb1c7000-7007fb1c8000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb1c8000-7007fb1e8000 r--s 00000000 00:13 6697                       /dev/__properties__/u:object_r:debug_prop:s0
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb1e8000-7007fb1e9000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fb1e9000-7007fb1ea000 rw-p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb1ea000-7007fb1eb000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fb1eb000-7007fb20b000 r--s 00000000 00:13 6750                       /dev/__properties__/properties_serial
-Size:                128 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb20b000-7007fb20c000 rw-p 00000000 00:00 0                          [anon:System property context nodes]
-Name:           [anon:System property context nodes]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb20c000-7007fb20f000 r--s 00000000 00:13 6672                       /dev/__properties__/property_info
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         12 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr me ms 
-7007fb20f000-7007fb210000 r--p 00000000 00:00 0                          [anon:linker_alloc]
-Name:           [anon:linker_alloc]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd mr mw me ac 
-7007fb210000-7007fb212000 rw-p 00000000 00:00 0                          [anon:linker_alloc_small_objects]
-Name:           [anon:linker_alloc_small_objects]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   8 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:             8 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007fb212000-7007fb213000 r--p 00000000 00:00 0                          [anon:atexit handlers]
-Name:           [anon:atexit handlers]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fb213000-7007fb214000 ---p 00000000 00:00 0                          [anon:thread signal stack guard]
-Name:           [anon:thread signal stack guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me ac 
-7007fb214000-7007fb21c000 rw-p 00000000 00:00 0                          [anon:thread signal stack]
-Name:           [anon:thread signal stack]
-Size:                 32 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd wr mr mw me ac 
-7007fb21c000-7007fb21d000 rw-p 00000000 00:00 0                          [anon:arc4random data]
-Name:           [anon:arc4random data]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me ac 
-7007fb21d000-7007fb21e000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fb21e000-7007fb221000 rw-p 00000000 00:00 0                          [anon:bionic TLS]
-Name:           [anon:bionic TLS]
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007fb221000-7007fb222000 ---p 00000000 00:00 0                          [anon:bionic TLS guard]
-Name:           [anon:bionic TLS guard]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me 
-7007fb222000-7007fb267000 r--p 00000000 fe:00 312                        /system/bin/linker64
-Size:                276 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 116 kB
-Pss:                   1 kB
-Shared_Clean:        116 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          116 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                1 kB
-VmFlags: rd mr mw me dw 
-7007fb267000-7007fb355000 r-xp 00045000 fe:00 312                        /system/bin/linker64
-Size:                952 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 496 kB
-Pss:                   7 kB
-Shared_Clean:        496 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:          496 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                7 kB
-VmFlags: rd ex mr mw me dw 
-7007fb355000-7007fb356000 rw-p 00133000 fe:00 312                        /system/bin/linker64
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   4 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         4 kB
-Referenced:            4 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                4 kB
-VmFlags: rd wr mr mw me dw ac 
-7007fb356000-7007fb361000 r--p 00134000 fe:00 312                        /system/bin/linker64
-Size:                 44 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  44 kB
-Pss:                   2 kB
-Shared_Clean:          0 kB
-Shared_Dirty:         44 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:           12 kB
-Anonymous:            44 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                2 kB
-VmFlags: rd mr mw me dw ac 
-7007fb361000-7007fb368000 rw-p 00000000 00:00 0 
-Size:                 28 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                   8 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         8 kB
-Referenced:            8 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                8 kB
-VmFlags: rd wr mr mw me ac 
-7007fb368000-7007fb369000 r--p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          4 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             4 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr mw me ac 
-7007fb369000-7007fb36c000 rw-p 00000000 00:00 0 
-Size:                 12 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  12 kB
-Pss:                  12 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:        12 kB
-Referenced:           12 kB
-Anonymous:            12 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               12 kB
-VmFlags: rd wr mr mw me ac 
-7ffde4f08000-7ffde4f09000 ---p 00000000 00:00 0 
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: mr mw me gd ac 
-7ffde4f09000-7ffde5708000 rw-p 00000000 00:00 0                          [stack]
-Size:               8188 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                  40 kB
-Pss:                  32 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          8 kB
-Private_Clean:         0 kB
-Private_Dirty:        32 kB
-Referenced:           36 kB
-Anonymous:            40 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:               32 kB
-VmFlags: rd wr mr mw me gd ac 
-7ffde5771000-7ffde5773000 r--p 00000000 00:00 0                          [vvar]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd mr pf io de dd 
-7ffde5773000-7ffde5775000 r-xp 00000000 00:00 0                          [vdso]
-Size:                  8 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   4 kB
-Pss:                   0 kB
-Shared_Clean:          4 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            4 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex mr mw me de 
-ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex 
diff --git a/libmeminfo/testdata1/smaps_short b/libmeminfo/testdata1/smaps_short
deleted file mode 100644
index cee67b3..0000000
--- a/libmeminfo/testdata1/smaps_short
+++ /dev/null
@@ -1,122 +0,0 @@
-54c00000-56c00000 r-xp 00000000 00:00 0                                  [anon:dalvik-zygote-jit-code-cache]
-Name:           [anon:dalvik-zygote-jit-code-cache]
-Size:              32768 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                2048 kB
-Pss:                 113 kB
-Shared_Clean:          0 kB
-Shared_Dirty:       2048 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         2048 kB
-Anonymous:          2048 kB
-AnonHugePages:      2048 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              113 kB
-VmFlags: rd ex mr mw me ac 
-701ea000-70cdb000 rw-p 00000000 fe:00 3165                               /system/framework/x86_64/boot-framework.art
-Size:              11204 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               11188 kB
-Pss:                2200 kB
-Shared_Clean:         80 kB
-Shared_Dirty:       9448 kB
-Private_Clean:         0 kB
-Private_Dirty:      1660 kB
-Referenced:         9892 kB
-Anonymous:         11108 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             2200 kB
-VmFlags: rd wr mr mw me ac 
-70074dd8d000-70074ee0d000 rw-p 00000000 00:00 0                          [anon:libc_malloc]
-Name:           [anon:libc_malloc]
-Size:              16896 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:               15272 kB
-Pss:               15272 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:     15272 kB
-Referenced:        11156 kB
-Anonymous:         15272 kB
-AnonHugePages:      6144 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:            15272 kB
-VmFlags: rd wr mr mw me ac 
-700755a2d000-700755a6e000 r-xp 00016000 fe:00 1947                       /system/priv-app/SettingsProvider/oat/x86_64/SettingsProvider.odex
-Size:                260 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                 260 kB
-Pss:                 260 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:       260 kB
-Private_Dirty:         0 kB
-Referenced:          260 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:              260 kB
-VmFlags: rd ex mr mw me 
-7007f85b0000-7007f8b9b000 r-xp 001ee000 fe:00 1537                       /system/lib64/libhwui.so
-Size:               6060 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                4132 kB
-Pss:                1274 kB
-Shared_Clean:       4132 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:         4132 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:             1274 kB
-VmFlags: rd ex mr mw me 
-ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
-Size:                  4 kB
-KernelPageSize:        4 kB
-MMUPageSize:           4 kB
-Rss:                   0 kB
-Pss:                   0 kB
-Shared_Clean:          0 kB
-Shared_Dirty:          0 kB
-Private_Clean:         0 kB
-Private_Dirty:         0 kB
-Referenced:            0 kB
-Anonymous:             0 kB
-AnonHugePages:         0 kB
-ShmemPmdMapped:        0 kB
-Shared_Hugetlb:        0 kB
-Private_Hugetlb:       0 kB
-Swap:                  0 kB
-SwapPss:               0 kB
-Locked:                0 kB
-VmFlags: rd ex 
diff --git a/libmeminfo/testdata1/vmallocinfo b/libmeminfo/testdata1/vmallocinfo
deleted file mode 100644
index d48d8bf..0000000
--- a/libmeminfo/testdata1/vmallocinfo
+++ /dev/null
@@ -1,1774 +0,0 @@
-0x0000000000000000-0x0000000000000000   69632 of_iomap+0x78/0xb0 phys=17a00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=b220000 ioremap

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17c90000 ioremap

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=17ca0000 ioremap

-0x0000000000000000-0x0000000000000000  266240 atomic_pool_init+0x0/0x200 user

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=146bf000 ioremap

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=146bf000 ioremap

-0x0000000000000000-0x0000000000000000   28672 devm_ioremap_resource+0xd8/0x194 phys=8c0000 ioremap

-0x0000000000000000-0x0000000000000000   28672 devm_ioremap_resource+0xd8/0x194 phys=ac0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=146bf000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=c264000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap_resource+0xd8/0x194 phys=c440000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17980000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 glink_mailbox_probe+0x55c/0xac4 phys=1885000 ioremap

-0x0000000000000000-0x0000000000000000  159744 devm_ioremap_resource+0xd8/0x194 phys=c40a000 ioremap

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   36864 remote_spinlock_init_address+0x1c8/0x224 phys=1f40000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000    8192 glink_mailbox_probe+0x634/0xac4 phys=1886000 ioremap

-0x0000000000000000-0x0000000000000000 1052672 of_iomap+0x78/0xb0 phys=17a60000 ioremap

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000   73728 msm_watchdog_probe+0x5b8/0xc24 user

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=179e0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=af20000 ioremap

-0x0000000000000000-0x0000000000000000   32768 msm_smem_probe+0x56c/0xdf0 phys=778000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=179e0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 glink_smem_native_probe+0x42c/0x934 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=af21000 ioremap

-0x0000000000000000-0x0000000000000000    8192 glink_smem_native_probe+0x42c/0x934 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 glink_smem_native_probe+0x42c/0x934 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 glink_smem_native_probe+0x42c/0x934 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=85fe0000 ioremap

-0x0000000000000000-0x0000000000000000   40960 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000  167936 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000   69632 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000   69632 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000   40960 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=ff1000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=16b000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=18d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=175000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=177000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=10f000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=110000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000 1052672 devm_ioremap_resource+0xd8/0x194 phys=e600000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ad06000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ad09000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ad0a000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ad07000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ad08000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ad0b000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=af03000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=5091000 ioremap

-0x0000000000000000-0x0000000000000000    8192 syscon_node_to_regmap+0x198/0x2dc phys=5091000 ioremap

-0x0000000000000000-0x0000000000000000    8192 syscon_node_to_regmap+0x198/0x2dc phys=5091000 ioremap

-0x0000000000000000-0x0000000000000000    8192 syscon_node_to_regmap+0x198/0x2dc phys=5091000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ab00000 ioremap

-0x0000000000000000-0x0000000000000000  135168 _persistent_ram_buffer_map+0x1ec/0x238 phys=a1810000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ab00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=ab00000 ioremap

-0x0000000000000000-0x0000000000000000   12288 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c5000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000   40960 devm_ioremap+0x84/0xd8 phys=5090000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c9000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150cd000 ioremap

-0x0000000000000000-0x0000000000000000  135168 _persistent_ram_buffer_map+0x1ec/0x238 phys=a1830000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000   20480 msm_bus_noc_qos_init+0x94/0x714 phys=10b8000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150d1000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150d5000 ioremap

-0x0000000000000000-0x0000000000000000   40960 devm_ioremap_resource+0xd8/0x194 phys=5090000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150d9000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000  135168 _persistent_ram_buffer_map+0x1ec/0x238 phys=a1850000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150dd000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150e1000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=150c2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=c222000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=c263000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=c223000 ioremap

-0x0000000000000000-0x0000000000000000   69632 devm_ioremap_resource+0xd8/0x194 phys=ad00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=c265000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap+0x84/0xd8 phys=1c08000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap+0x84/0xd8 phys=1c0a000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=40000000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=40000000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=5091000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap+0x84/0xd8 phys=17d41000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap+0x84/0xd8 phys=17d43000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap+0x84/0xd8 phys=17d45000 ioremap

-0x0000000000000000-0x0000000000000000    8192 syscon_node_to_regmap+0x198/0x2dc phys=17970000 ioremap

-0x0000000000000000-0x0000000000000000  659456 devm_ioremap_resource+0xd8/0x194 phys=e700000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x208/0x77c phys=ae94000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x360/0x77c phys=ae94000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x4f0/0x77c phys=af03000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x208/0x77c phys=ae96000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x360/0x77c phys=ae96000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x4f0/0x77c phys=af03000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x208/0x77c phys=88ea000 ioremap

-0x0000000000000000-0x0000000000000000   40960 syscon_node_to_regmap+0x198/0x2dc phys=5090000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x360/0x77c phys=88ea000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x428/0x77c phys=88ea000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x48c/0x77c phys=88ea000 ioremap

-0x0000000000000000-0x0000000000000000  135168 _persistent_ram_buffer_map+0x1ec/0x238 phys=a1870000 ioremap

-0x0000000000000000-0x0000000000000000    8192 mdss_pll_probe+0x4f0/0x77c phys=af03000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=1d87000 ioremap

-0x0000000000000000-0x0000000000000000   12288 pcpu_alloc+0x3e8/0x9e4 pages=2 vmalloc

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap_resource+0xd8/0x194 phys=88e0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_smp2p_probe+0xb0/0x3b0 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_smp2p_probe+0xb0/0x3b0 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_smp2p_probe+0xb0/0x3b0 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_smp2p_probe+0xb0/0x3b0 phys=17990000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_pil_init+0xe4/0x250 phys=146bf000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=1881000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=1881000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=1881000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=1881000 ioremap

-0x0000000000000000-0x0000000000000000 2101248 msm_smem_probe+0x23c/0xdf0 phys=86000000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=1882000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   69632 devm_ioremap_resource+0xd8/0x194 phys=af00000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=b221000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qsee_ipc_irq_bridge_probe+0x414/0xb0c phys=1888000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_rng_probe+0x90/0x4a8 phys=793000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=ae94000 ioremap

-0x0000000000000000-0x0000000000000000   69632 devm_ioremap_resource+0xd8/0x194 phys=ab00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=ae96000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap+0x84/0xd8 phys=898000 ioremap

-0x0000000000000000-0x0000000000000000   24576 diag_dci_init+0x25c/0x35c pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   69632 devm_ioremap_resource+0xd8/0x194 phys=5040000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=ae94000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap+0x84/0xd8 phys=a84000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=af08000 ioremap

-0x0000000000000000-0x0000000000000000   20480 msm_dss_ioremap_byname+0x84/0x134 phys=af30000 ioremap

-0x0000000000000000-0x0000000000000000   12288 msm_dss_ioremap_byname+0x84/0x134 phys=af20000 ioremap

-0x0000000000000000-0x0000000000000000   20480 alloc_and_map+0xb0/0x1cc user

-0x0000000000000000-0x0000000000000000   20480 alloc_and_map+0xb0/0x1cc user

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=16e0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_sharedmem_alloc_contig+0xc4/0x1f8 user

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   16384 devm_ioremap_resource+0xd8/0x194 phys=1d84000 ioremap

-0x0000000000000000-0x0000000000000000   69632 syscon_node_to_regmap+0x198/0x2dc phys=af00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   16384 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   20480 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 dmam_alloc_coherent+0xb0/0x11c user

-0x0000000000000000-0x0000000000000000    8192 dmam_alloc_coherent+0xb0/0x11c user

-0x0000000000000000-0x0000000000000000 1052672 devm_ioremap_nocache+0x84/0xd8 phys=c300000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=5061000 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   69632 syscon_node_to_regmap+0x198/0x2dc phys=ab00000 ioremap

-0x0000000000000000-0x0000000000000000   65536 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1700000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   16384 devm_ioremap_nocache+0x84/0xd8 phys=88e8000 ioremap

-0x0000000000000000-0x0000000000000000   69632 syscon_node_to_regmap+0x198/0x2dc phys=ad00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000   65536 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   20480 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=88e2000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=780000 ioremap

-0x0000000000000000-0x0000000000000000  217088 ipa3_pre_init+0x984/0x20c4 phys=1e40000 ioremap

-0x0000000000000000-0x0000000000000000   20480 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=88e7000 ioremap

-0x0000000000000000-0x0000000000000000 1052672 _persistent_ram_buffer_map+0x1ec/0x238 phys=a1890000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 msm_slim_sps_mem_alloc+0xb8/0x130 user

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000  528384 _persistent_ram_buffer_map+0x1ec/0x238 phys=a1990000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   40960 qce_sps_init_ep_conn+0x168/0x348 user

-0x0000000000000000-0x0000000000000000   77824 sps_bam_pipe_set_params+0x1e4/0x4c8 pages=18 vmalloc

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1620000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   40960 qce_sps_init_ep_conn+0x168/0x348 user

-0x0000000000000000-0x0000000000000000   40960 qce_sps_init_ep_conn+0x168/0x348 user

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap+0x84/0xd8 phys=880000 ioremap

-0x0000000000000000-0x0000000000000000 2035712 devm_ioremap_resource+0xd8/0x194 phys=100000 ioremap

-0x0000000000000000-0x0000000000000000   40960 qce_sps_init_ep_conn+0x168/0x348 user

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=a6f8000 ioremap

-0x0000000000000000-0x0000000000000000    8192 of_iomap+0x78/0xb0 phys=146bf000 ioremap

-0x0000000000000000-0x0000000000000000 12587008 devm_ioremap_resource+0xd8/0x194 phys=3400000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   77824 sps_bam_pipe_set_params+0x1e4/0x4c8 pages=18 vmalloc

-0x0000000000000000-0x0000000000000000   36864 kgsl_sharedmem_alloc_contig+0xc4/0x1f8 user

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac40000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1500000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   77824 sps_bam_pipe_set_params+0x1e4/0x4c8 pages=18 vmalloc

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac48000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap+0x84/0xd8 phys=890000 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=acb3000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=14e0000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   77824 sps_bam_pipe_set_params+0x1e4/0x4c8 pages=18 vmalloc

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=acba000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap+0x84/0xd8 phys=89c000 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=acc8000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=17900000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac65000 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac66000 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac67000 ioremap

-0x0000000000000000-0x0000000000000000   36864 devm_ioremap_resource+0xd8/0x194 phys=1d90000 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac68000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap+0x84/0xd8 phys=a8c000 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac5a000 ioremap

-0x0000000000000000-0x0000000000000000   16384 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac18000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1620000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000  102400 dmam_alloc_coherent+0xb0/0x11c user

-0x0000000000000000-0x0000000000000000   16384 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac87000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1380000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac5b000 ioremap

-0x0000000000000000-0x0000000000000000   16384 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac91000 ioremap

-0x0000000000000000-0x0000000000000000   36864 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac6b000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=888000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d78000 ioremap

-0x0000000000000000-0x0000000000000000   16384 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac6f000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1380000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d43000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d78000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d70000 ioremap

-0x0000000000000000-0x0000000000000000   36864 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d45000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=88c000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=17d70000 ioremap

-0x0000000000000000-0x0000000000000000   12288 devm_ioremap_nocache+0x84/0xd8 phys=858b2000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1740000 ioremap

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000  135168 crypto_scomp_alloc_scratches+0x74/0xdc pages=32 vmalloc

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=894000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=1436000 ioremap

-0x0000000000000000-0x0000000000000000   16384 devm_ioremap_nocache+0x84/0xd8 phys=14693000 ioremap

-0x0000000000000000-0x0000000000000000   69632 kgsl_iommu_init+0x154/0x5a0 phys=5040000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=1436000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=114a000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=170f7000 ioremap

-0x0000000000000000-0x0000000000000000   36864 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=170f7000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ebt_register_table+0xc4/0x3d4 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 ebt_register_table+0xd4/0x3d4 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   24576 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac42000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=4080000 ioremap

-0x0000000000000000-0x0000000000000000 33558528 devm_ioremap_resource+0xd8/0x194 phys=c600000 ioremap

-0x0000000000000000-0x0000000000000000 33558528 mem_dump_probe+0x1d4/0x464 user

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=1f63000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=1f65000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=1f64000 ioremap

-0x0000000000000000-0x0000000000000000   36864 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=4180000 ioremap

-0x0000000000000000-0x0000000000000000   20480 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=acaf000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=c2b0000 ioremap

-0x0000000000000000-0x0000000000000000   20480 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=acb6000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=b2e0000 ioremap

-0x0000000000000000-0x0000000000000000   20480 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=acc4000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap+0x84/0xd8 phys=4180000 ioremap

-0x0000000000000000-0x0000000000000000   20480 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac4a000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   28672 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac00000 ioremap

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1620000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   36864 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac10000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   20480 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac4e000 ioremap

-0x0000000000000000-0x0000000000000000   20480 cam_soc_util_request_platform_resource+0xd4/0x5e8 phys=ac52000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=a88000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_resource+0xd8/0x194 phys=a90000 ioremap

-0x0000000000000000-0x0000000000000000   20480 devm_ioremap_nocache+0x84/0xd8 phys=146bf000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1380000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=88ee000 ioremap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_resource+0xd8/0x194 phys=a60c000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init+0x15c/0x5c0 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init+0x1d0/0x5c0 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init+0x2a0/0x5c0 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1380000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 __ipa_commit_hdr_v3_0+0x19c/0xefc user

-0x0000000000000000-0x0000000000000000   20480 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=1740000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_gadget_init_hw_endpoints+0x2a4/0x368 user

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   98304 sps_register_bam_device+0x884/0xd9c phys=a704000 ioremap

-0x0000000000000000-0x0000000000000000    8192 dwc3_core_pre_init+0x438/0x480 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_msm_notify_event+0x704/0xee0 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_msm_notify_event+0x704/0xee0 user

-0x0000000000000000-0x0000000000000000    8192 dwc3_msm_notify_event+0x704/0xee0 user

-0x0000000000000000-0x0000000000000000  200704 devm_ioremap+0x84/0xd8 phys=506a000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 devm_ioremap_nocache+0x84/0xd8 phys=aeac000 ioremap

-0x0000000000000000-0x0000000000000000   16384 devm_ioremap_nocache+0x84/0xd8 phys=aeb0000 ioremap

-0x0000000000000000-0x0000000000000000  528384 devm_ioremap_resource+0xd8/0x194 phys=15000000 ioremap

-0x0000000000000000-0x0000000000000000   24576 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   20480 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000  135168 qce_open+0x360/0x1760 phys=1de0000 ioremap

-0x0000000000000000-0x0000000000000000   36864 drm_ht_create+0x50/0x84 pages=8 vmalloc

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   12288 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   45056 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   12288 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   45056 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   12288 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000  397312 devm_ioremap_nocache+0x84/0xd8 phys=800000 ioremap

-0x0000000000000000-0x0000000000000000   45056 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   12288 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000   45056 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000  139264 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000  106496 mnh_alloc_coherent+0x94/0xd0 user

-0x0000000000000000-0x0000000000000000    8192 firmware_data_write+0xe8/0x228 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 firmware_loading_store+0x1b8/0x244

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 firmware_data_write+0xe8/0x228 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 firmware_loading_store+0x1b8/0x244

-0x0000000000000000-0x0000000000000000   12288 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 SyS_swapon+0x720/0xd20 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 swap_cgroup_swapon+0x38/0x140 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000  528384 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 disksize_store+0x9c/0x154 pages=2 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000   24576 lz4_init+0x1c/0x48 pages=5 vmalloc

-0x0000000000000000-0x0000000000000000    8192 ipa3_uc_event_handler+0x378/0x6c8 phys=1e47000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipa3_uc_wdi_event_log_info_handler+0x1bc/0x350 phys=1e47000 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000  110592 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   16384 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   40960 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   40960 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   16384 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   16384 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000  249856 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000  266240 SyS_swapon+0x650/0xd20 pages=64 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_multi_pages_alloc+0x388/0x64c [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   20480 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000  139264 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   20480 pcpu_alloc+0x3e8/0x9e4 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000 1052672 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000 20975616 memremap+0x188/0x200 phys=8ab00000 ioremap

-0x0000000000000000-0x0000000000000000  372736 qce_open+0x68c/0x1760 user

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000  397312 devm_ioremap_nocache+0x84/0xd8 phys=a00000 ioremap

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   12288 lpm_probe+0x194/0x2e4 user

-0x0000000000000000-0x0000000000000000 1052672 devm_ioremap+0x84/0xd8 phys=40100000 ioremap

-0x0000000000000000-0x0000000000000000 1052672 msm_rtb_probe+0x114/0x268 user

-0x0000000000000000-0x0000000000000000    8192 pci_ioremap_bar+0x80/0xb4 phys=41c00000 ioremap

-0x0000000000000000-0x0000000000000000   16384 sde_rot_ioremap_byname+0x84/0x144 phys=aeb8000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   61440 verity_ctr+0x6c4/0x8c4 pages=14 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000  266240 devm_ioremap+0x84/0xd8 phys=5000000 ioremap

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   20480 verity_ctr+0x6c4/0x8c4 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000   32768 verity_ctr+0x6c4/0x8c4 pages=7 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 alloc_buffer+0x16c/0x208 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000  151552 qce_open+0xc08/0x1760 phys=1dc4000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   20480 load_module+0x24ac/0x3408 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000    8192 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000    8192 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000   12288 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 dm_create+0x78/0x490 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000 4198400 disksize_store+0x9c/0x154 pages=1024 vmalloc vpages

-0x0000000000000000-0x0000000000000000 1052672 devm_ioremap+0x84/0xd8 phys=40200000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 dm_table_create+0x84/0xf0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000  135168 qce_open+0x360/0x1760 phys=1de0000 ioremap

-0x0000000000000000-0x0000000000000000  372736 qce_open+0x68c/0x1760 user

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000  200704 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 kgsl_sharedmem_alloc_contig+0xc4/0x1f8 user

-0x0000000000000000-0x0000000000000000 2035712 syscon_node_to_regmap+0x198/0x2dc phys=100000 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   16384 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000 2428928 syscon_node_to_regmap+0x198/0x2dc phys=1100000 ioremap

-0x0000000000000000-0x0000000000000000 1052672 dmam_alloc_coherent+0xb0/0x11c user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000  266240 usbpd_create+0x3c/0x824 pages=64 vmalloc

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   36864 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   36864 alloc_and_map+0xb0/0x1cc user

-0x0000000000000000-0x0000000000000000   12288 kgsl_sharedmem_page_alloc_user+0x114/0x4ec pages=2 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   12288 kgsl_sharedmem_page_alloc_user+0x114/0x4ec pages=2 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   12288 kgsl_sharedmem_page_alloc_user+0x114/0x4ec pages=2 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000 3149824 devm_ioremap+0x84/0xd8 phys=b200000 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000   12288 kgsl_sharedmem_page_alloc_user+0x114/0x4ec pages=2 vmalloc

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   36864 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000   20480 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 qdf_mem_alloc_consistent_debug+0xd4/0x148 [wlan] user

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x131c/0x2794 user

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x14cc/0x2794 user

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x131c/0x2794 user

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x14cc/0x2794 user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000  184320 ngd_slim_probe+0x334/0x9b0 phys=171c0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000  176128 ngd_slim_probe+0x378/0x9b0 phys=17184000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000  184320 ngd_slim_probe+0x334/0x9b0 phys=17240000 ioremap

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000   16384 n_tty_open+0x1c/0xac pages=3 vmalloc

-0x0000000000000000-0x0000000000000000    8192 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000   12288 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000 8392704 devm_ioremap+0x84/0xd8 phys=18800000 ioremap

-0x0000000000000000-0x0000000000000000 2109440 msm_sharedmem_probe+0x1dc/0x354 user

-0x0000000000000000-0x0000000000000000   16384 fastrpc_internal_invoke+0xab8/0x1c50 user

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000   28672 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=6 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 drm_property_create_blob+0x44/0xec pages=1 vmalloc

-0x0000000000000000-0x0000000000000000  135168 ngd_slim_probe+0x378/0x9b0 phys=17204000 ioremap

-0x0000000000000000-0x0000000000000000   12288 pcpu_alloc+0x3e8/0x9e4 pages=2 vmalloc

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 rpmstats_show+0x78/0x2b0 phys=c3f0000 ioremap

-0x0000000000000000-0x0000000000000000   12288 drm_property_create_blob+0x44/0xec pages=2 vmalloc

-0x0000000000000000-0x0000000000000000    8192 msm_gem_get_vaddr+0xb0/0xf0 vmap

-0x0000000000000000-0x0000000000000000    8192 wlan_logging_sock_init_svc+0xf8/0x4f0 [wlan] pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000    8192 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000 1052672 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000 2101248 devm_ioremap_nocache+0x84/0xd8 phys=aa00000 ioremap

-0x0000000000000000-0x0000000000000000   45056 drm_property_create_blob+0x44/0xec pages=10 vmalloc

-0x0000000000000000-0x0000000000000000  135168 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000  135168 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000   12288 gpi_alloc_ring+0x238/0x2e0 user

-0x0000000000000000-0x0000000000000000 1052672 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_init+0x9e4/0xc7c user

-0x0000000000000000-0x0000000000000000 1024000 devm_ioremap_nocache+0x84/0xd8 phys=a600000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipa3_allocate_dma_task_for_gsi+0xfc/0x318 user

-0x0000000000000000-0x0000000000000000    8192 ipa3_nat_ipv6ct_init_devices+0x160/0x438 user

-0x0000000000000000-0x0000000000000000  536576 devm_ioremap_nocache+0x84/0xd8 phys=ae00000 ioremap

-0x0000000000000000-0x0000000000000000  708608 sde_rot_ioremap_byname+0x84/0x144 phys=ae00000 ioremap

-0x0000000000000000-0x0000000000000000 33558528 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 8392704 pci_ioremap_bar+0x80/0xb4 phys=40800000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipa3_post_init+0x7fc/0x2c98 user

-0x0000000000000000-0x0000000000000000  442368 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 4198400 pci_ioremap_bar+0x80/0xb4 phys=41800000 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1052672 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000   36864 ipa3_alloc_common_event_ring+0x178/0x24c user

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 2166784 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x131c/0x2794 user

-0x0000000000000000-0x0000000000000000   12288 ipa3_setup_sys_pipe+0x14cc/0x2794 user

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 2166784 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x131c/0x2794 user

-0x0000000000000000-0x0000000000000000 2166784 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipa3_setup_sys_pipe+0x14cc/0x2794 user

-0x0000000000000000-0x0000000000000000   20480 ipa3_setup_sys_pipe+0x14cc/0x2794 user

-0x0000000000000000-0x0000000000000000    8192 ipa3_uc_interface_init+0x104/0x390 phys=1e47000 ioremap

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000    8192 ipahal_fltrt_allocate_hw_sys_tbl+0x1cc/0x34c user

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000  184320 devm_ioremap_nocache+0x84/0xd8 phys=1e04000 ioremap

-0x0000000000000000-0x0000000000000000  266240 bpf_map_area_alloc+0x74/0x94 pages=64 vmalloc

-0x0000000000000000-0x0000000000000000  266240 bpf_map_area_alloc+0x74/0x94 pages=64 vmalloc

-0x0000000000000000-0x0000000000000000  266240 bpf_map_area_alloc+0x74/0x94 pages=64 vmalloc

-0x0000000000000000-0x0000000000000000 2166784 kgsl_page_alloc_map_kernel+0x70/0x108 ioremap

-0x0000000000000000-0x0000000000000000  266240 bpf_map_area_alloc+0x74/0x94 pages=64 vmalloc

-0x0000000000000000-0x0000000000000000  700416 ipa3_qmi_service_init_worker+0x78/0x55c pages=170 vmalloc

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000    8192 bpf_prog_alloc+0x70/0xd0 pages=1 vmalloc

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 5246976 removed_alloc+0x2f8/0x3ac phys=8bf00000 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1052672 removed_alloc+0x2f8/0x3ac phys=98500000 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 3141632 ion_heap_map_kernel+0x108/0x158 vmap

-0x0000000000000000-0x0000000000000000 533729280 devm_ioremap+0x84/0xd8 phys=40300000 ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 1044480 binder_alloc_mmap_handler+0x60/0x1cc ioremap

-0x0000000000000000-0x0000000000000000 10498048 pktlog_alloc_buf+0xc4/0x15c [wlan] pages=2562 vmalloc vpages

-0x0000000000000000-0x0000000000000000 18350080 setup_arch+0x20c/0x668 phys=80080000 vmap

-0x0000000000000000-0x0000000000000000 8388608 setup_arch+0x20c/0x668 phys=81200000 vmap

-0x0000000000000000-0x0000000000000000 6291456 setup_arch+0x20c/0x668 phys=81a00000 vmap

-0x0000000000000000-0x0000000000000000 11005952 setup_arch+0x20c/0x668 phys=82000000 vmap

-0x0000000000000000-0x0000000000000000 8073216 load_module+0x24ac/0x3408 pages=1970 vmalloc vpages

-0x0000000000000000-0x0000000000000000   20480 load_module+0x24ac/0x3408 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000  151552 load_module+0x24ac/0x3408 pages=36 vmalloc

-0x0000000000000000-0x0000000000000000   28672 load_module+0x24ac/0x3408 pages=6 vmalloc

-0x0000000000000000-0x0000000000000000   94208 load_module+0x24ac/0x3408 pages=22 vmalloc

-0x0000000000000000-0x0000000000000000  409600 load_module+0x24ac/0x3408 pages=99 vmalloc

-0x0000000000000000-0x0000000000000000   36864 load_module+0x24ac/0x3408 pages=8 vmalloc

-0x0000000000000000-0x0000000000000000  303104 load_module+0x24ac/0x3408 pages=73 vmalloc

-0x0000000000000000-0x0000000000000000  172032 load_module+0x24ac/0x3408 pages=41 vmalloc

-0x0000000000000000-0x0000000000000000   20480 load_module+0x24ac/0x3408 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000   20480 load_module+0x24ac/0x3408 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000   20480 load_module+0x24ac/0x3408 pages=4 vmalloc

-0x0000000000000000-0x0000000000000000  245760 load_module+0x24ac/0x3408 pages=59 vmalloc

-0x0000000000000000-0x0000000000000000  786432 pcpu_get_vm_areas+0x0/0x800 vmalloc

-0x0000000000000000-0x0000000000000000  786432 pcpu_get_vm_areas+0x0/0x800 vmalloc

diff --git a/libmeminfo/testdata2/mem_used_total b/libmeminfo/testdata2/mem_used_total
deleted file mode 100644
index 97fcf41..0000000
--- a/libmeminfo/testdata2/mem_used_total
+++ /dev/null
@@ -1 +0,0 @@
-31236096
diff --git a/libmeminfo/tools/Android.bp b/libmeminfo/tools/Android.bp
deleted file mode 100644
index 2e89c41..0000000
--- a/libmeminfo/tools/Android.bp
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.
-
-cc_binary {
-    name: "librank",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    srcs: ["librank.cpp"],
-    shared_libs: [
-        "libbase",
-        "libmeminfo",
-    ],
-}
-
-cc_binary {
-    name: "procmem",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    srcs: ["procmem.cpp"],
-    shared_libs: [
-        "libbase",
-        "libmeminfo",
-    ],
-}
-
-cc_binary {
-    name: "procrank",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    srcs: ["procrank.cpp"],
-    shared_libs: [
-        "libbase",
-        "libmeminfo",
-    ],
-}
-
-cc_binary {
-    name: "showmap",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    srcs: ["showmap.cpp"],
-    shared_libs: [
-        "libbase",
-        "libmeminfo",
-    ],
-}
-
-cc_binary {
-    name: "wsstop",
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    srcs: ["wsstop.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libmeminfo",
-    ],
-}
diff --git a/libmeminfo/tools/librank.cpp b/libmeminfo/tools/librank.cpp
deleted file mode 100644
index e53c746..0000000
--- a/libmeminfo/tools/librank.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * 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.
- */
-
-#include <dirent.h>
-#include <errno.h>
-#include <error.h>
-#include <inttypes.h>
-#include <linux/kernel-page-flags.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <map>
-#include <memory>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/parseint.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-
-#include <meminfo/procmeminfo.h>
-
-using ::android::meminfo::MemUsage;
-using ::android::meminfo::ProcMemInfo;
-using ::android::meminfo::Vma;
-
-[[noreturn]] static void usage(int exit_status) {
-    fprintf(stderr,
-            "Usage: %s [ -P | -L ] [ -v | -r | -p | -u | -s | -h ]\n"
-            "\n"
-            "Sort options:\n"
-            "    -v  Sort processes by VSS.\n"
-            "    -r  Sort processes by RSS.\n"
-            "    -p  Sort processes by PSS.\n"
-            "    -u  Sort processes by USS.\n"
-            "    -s  Sort processes by swap.\n"
-            "        (Default sort order is PSS.)\n"
-            "    -a  Show all mappings, including stack, heap and anon.\n"
-            "    -P /path  Limit libraries displayed to those in path.\n"
-            "    -R  Reverse sort order (default is descending).\n"
-            "    -m [r][w][x] Only list pages that exactly match permissions\n"
-            "    -c  Only show cached (storage backed) pages\n"
-            "    -C  Only show non-cached (ram/swap backed) pages\n"
-            "    -k  Only show pages collapsed by KSM\n"
-            "    -h  Display this help screen.\n",
-            getprogname());
-    exit(exit_status);
-}
-
-static void add_mem_usage(MemUsage* to, const MemUsage& from) {
-    to->vss += from.vss;
-    to->rss += from.rss;
-    to->pss += from.pss;
-    to->uss += from.uss;
-
-    to->swap += from.swap;
-
-    to->private_clean += from.private_clean;
-    to->private_dirty += from.private_dirty;
-
-    to->shared_clean += from.shared_clean;
-    to->shared_dirty += from.shared_dirty;
-}
-
-struct ProcessRecord {
-  public:
-    ProcessRecord(pid_t pid) : pid_(-1), cmdline_("") {
-        std::string fname = ::android::base::StringPrintf("/proc/%d/cmdline", pid);
-        std::string cmdline;
-        if (!::android::base::ReadFileToString(fname, &cmdline)) {
-            fprintf(stderr, "Failed to read cmdline from: %s\n", fname.c_str());
-            return;
-        }
-        // We deliberately don't read the proc/<pid>cmdline file directly into 'cmdline_'
-        // because of some processes showing up cmdlines that end with "0x00 0x0A 0x00"
-        // e.g. xtra-daemon, lowi-server
-        // The .c_str() assignment below then takes care of trimming the cmdline at the first
-        // 0x00. This is how original procrank worked (luckily)
-        cmdline_ = cmdline.c_str();
-        pid_ = pid;
-        usage_.clear();
-    }
-
-    ~ProcessRecord() = default;
-
-    bool valid() const { return pid_ != -1; }
-
-    // Getters
-    pid_t pid() const { return pid_; }
-    const std::string& cmdline() const { return cmdline_; }
-    const MemUsage& usage() const { return usage_; }
-
-    // Add to the usage
-    void AddUsage(const MemUsage& mem_usage) { add_mem_usage(&usage_, mem_usage); }
-
-  private:
-    pid_t pid_;
-    std::string cmdline_;
-    MemUsage usage_;
-};
-
-struct LibRecord {
-  public:
-    LibRecord(const std::string& name) : name_(name) {}
-    ~LibRecord() = default;
-
-    const std::string& name() const { return name_; }
-    const MemUsage& usage() const { return usage_; }
-    const std::map<pid_t, ProcessRecord>& processes() const { return procs_; }
-    uint64_t pss() const { return usage_.pss; }
-    void AddUsage(const ProcessRecord& proc, const MemUsage& mem_usage) {
-        auto [it, inserted] = procs_.insert(std::pair<pid_t, ProcessRecord>(proc.pid(), proc));
-        it->second.AddUsage(mem_usage);
-        add_mem_usage(&usage_, mem_usage);
-    }
-
-  private:
-    std::string name_;
-    MemUsage usage_;
-    std::map<pid_t, ProcessRecord> procs_;
-};
-
-// List of every library / map
-static std::map<std::string, LibRecord> g_libs;
-
-// List of library/map names that we don't want to show by default
-static const std::vector<std::string> g_blacklisted_libs = {"[heap]", "[stack]"};
-
-// Global flags affected by command line
-static uint64_t g_pgflags = 0;
-static uint64_t g_pgflags_mask = 0;
-static uint16_t g_mapflags_mask = 0;
-static bool g_all_libs = false;
-static bool g_has_swap = false;
-static bool g_reverse_sort = false;
-static std::string g_prefix_filter = "";
-
-static bool read_all_pids(std::function<bool(pid_t pid)> for_each_pid) {
-    std::unique_ptr<DIR, int (*)(DIR*)> procdir(opendir("/proc"), closedir);
-    if (!procdir) return false;
-
-    struct dirent* dir;
-    pid_t pid;
-    while ((dir = readdir(procdir.get()))) {
-        if (!::android::base::ParseInt(dir->d_name, &pid)) continue;
-        if (!for_each_pid(pid)) return false;
-    }
-
-    return true;
-}
-
-static bool scan_libs_per_process(pid_t pid) {
-    ProcMemInfo pmem(pid, false, g_pgflags, g_pgflags_mask);
-    const std::vector<Vma> maps = pmem.Maps();
-    if (maps.size() == 0) {
-        // nothing to do here, continue
-        return true;
-    }
-
-    ProcessRecord proc(pid);
-    if (!proc.valid()) {
-        fprintf(stderr, "Failed to create process record for process: %d\n", pid);
-        return false;
-    }
-
-    for (auto& map : maps) {
-        // skip library / map if prefix for the path doesn't match
-        if (!g_prefix_filter.empty() && !::android::base::StartsWith(map.name, g_prefix_filter)) {
-            continue;
-        }
-        // Skip maps based on map permissions
-        if (g_mapflags_mask &&
-            ((map.flags & (PROT_READ | PROT_WRITE | PROT_EXEC)) != g_mapflags_mask)) {
-            continue;
-        }
-
-        // skip blacklisted library / map names
-        if (!g_all_libs && (std::find(g_blacklisted_libs.begin(), g_blacklisted_libs.end(),
-                                      map.name) != g_blacklisted_libs.end())) {
-            continue;
-        }
-
-        auto [it, inserted] =
-            g_libs.insert(std::pair<std::string, LibRecord>(map.name, LibRecord(map.name)));
-        it->second.AddUsage(proc, map.usage);
-
-        if (!g_has_swap && map.usage.swap) {
-            g_has_swap = true;
-        }
-    }
-
-    return true;
-}
-
-static uint16_t parse_mapflags(const char* mapflags) {
-    uint16_t ret = 0;
-    for (const char* p = mapflags; *p; p++) {
-        switch (*p) {
-            case 'r':
-                ret |= PROT_READ;
-                break;
-            case 'w':
-                ret |= PROT_WRITE;
-                break;
-            case 'x':
-                ret |= PROT_EXEC;
-                break;
-            default:
-                error(EXIT_FAILURE, 0, "Invalid permissions string: %s, %s", mapflags, p);
-        }
-    }
-
-    return ret;
-}
-
-int main(int argc, char* argv[]) {
-    int opt;
-
-    auto pss_sort = [](const ProcessRecord& a, const ProcessRecord& b) {
-        return g_reverse_sort ? a.usage().pss < b.usage().pss : a.usage().pss > b.usage().pss;
-    };
-
-    auto uss_sort = [](const ProcessRecord& a, const ProcessRecord& b) {
-        return g_reverse_sort ? a.usage().uss < b.usage().uss : a.usage().uss > b.usage().uss;
-    };
-
-    auto vss_sort = [](const ProcessRecord& a, const ProcessRecord& b) {
-        return g_reverse_sort ? a.usage().vss < b.usage().vss : a.usage().vss > b.usage().vss;
-    };
-
-    auto rss_sort = [](const ProcessRecord& a, const ProcessRecord& b) {
-        return g_reverse_sort ? a.usage().rss < b.usage().rss : a.usage().rss > b.usage().rss;
-    };
-
-    auto swap_sort = [](const ProcessRecord& a, const ProcessRecord& b) {
-        return g_reverse_sort ? a.usage().swap < b.usage().swap : a.usage().swap > b.usage().swap;
-    };
-
-    std::function<bool(const ProcessRecord&, const ProcessRecord&)> sort_func = pss_sort;
-
-    while ((opt = getopt(argc, argv, "acChkm:pP:uvrsR")) != -1) {
-        switch (opt) {
-            case 'a':
-                g_all_libs = true;
-                break;
-            case 'c':
-                g_pgflags = 0;
-                g_pgflags_mask = (1 << KPF_SWAPBACKED);
-                break;
-            case 'C':
-                g_pgflags = g_pgflags_mask = (1 << KPF_SWAPBACKED);
-                break;
-            case 'h':
-                usage(EXIT_SUCCESS);
-            case 'k':
-                g_pgflags = g_pgflags_mask = (1 << KPF_KSM);
-                break;
-            case 'm':
-                g_mapflags_mask = parse_mapflags(optarg);
-                break;
-            case 'p':
-                sort_func = pss_sort;
-                break;
-            case 'P':
-                g_prefix_filter = optarg;
-                break;
-            case 'u':
-                sort_func = uss_sort;
-                break;
-            case 'v':
-                sort_func = vss_sort;
-                break;
-            case 'r':
-                sort_func = rss_sort;
-                break;
-            case 's':
-                sort_func = swap_sort;
-                break;
-            case 'R':
-                g_reverse_sort = true;
-                break;
-            default:
-                usage(EXIT_FAILURE);
-        }
-    }
-
-    if (!read_all_pids(scan_libs_per_process)) {
-        error(EXIT_FAILURE, 0, "Failed to read all pids from the system");
-    }
-
-    printf(" %6s   %7s   %6s   %6s   %6s  ", "RSStot", "VSS", "RSS", "PSS", "USS");
-    if (g_has_swap) {
-        printf(" %6s  ", "Swap");
-    }
-    printf("Name/PID\n");
-
-    std::vector<LibRecord> v_libs;
-    v_libs.reserve(g_libs.size());
-    std::transform(g_libs.begin(), g_libs.end(), std::back_inserter(v_libs),
-        [] (std::pair<std::string, LibRecord> const& pair) { return pair.second; });
-
-    // sort the libraries by their pss
-    std::sort(v_libs.begin(), v_libs.end(),
-              [](const LibRecord& l1, const LibRecord& l2) { return l1.pss() > l2.pss(); });
-
-    for (auto& lib : v_libs) {
-        printf("%6" PRIu64 "K   %7s   %6s   %6s   %6s  ", lib.pss() / 1024, "", "", "", "");
-        if (g_has_swap) {
-            printf(" %6s  ", "");
-        }
-        printf("%s\n", lib.name().c_str());
-
-        // sort all mappings first
-
-        std::vector<ProcessRecord> procs;
-        procs.reserve(lib.processes().size());
-        std::transform(lib.processes().begin(), lib.processes().end(), std::back_inserter(procs),
-            [] (std::pair<pid_t, ProcessRecord> const& pair) { return pair.second; });
-
-        std::sort(procs.begin(), procs.end(), sort_func);
-
-        for (auto& p : procs) {
-            const MemUsage& usage = p.usage();
-            printf(" %6s  %7" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ", "",
-                   usage.vss / 1024, usage.rss / 1024, usage.pss / 1024, usage.uss / 1024);
-            if (g_has_swap) {
-                printf("%6" PRIu64 "K  ", usage.swap / 1024);
-            }
-            printf("  %s [%d]\n", p.cmdline().c_str(), p.pid());
-        }
-    }
-
-    return 0;
-}
diff --git a/libmeminfo/tools/procmem.cpp b/libmeminfo/tools/procmem.cpp
deleted file mode 100644
index 47881ed..0000000
--- a/libmeminfo/tools/procmem.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.
- */
-
-#include <errno.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-#include <meminfo/procmeminfo.h>
-
-using Vma = ::android::meminfo::Vma;
-using ProcMemInfo = ::android::meminfo::ProcMemInfo;
-using MemUsage = ::android::meminfo::MemUsage;
-
-// Global flags to control procmem output
-
-// Set to use page idle bits for working set detection
-bool use_pageidle = false;
-// hides map entries with zero rss
-bool hide_zeroes = false;
-// Reset working set and exit
-bool reset_wss = false;
-// Show working set, mutually exclusive with reset_wss;
-bool show_wss = false;
-
-[[noreturn]] static void usage(int exit_status) {
-    fprintf(stderr,
-            "Usage: %s [-i] [ -w | -W ] [ -p | -m ] [ -h ] pid\n"
-            "    -i  Uses idle page tracking for working set statistics.\n"
-            "    -w  Displays statistics for the working set only.\n"
-            "    -W  Resets the working set of the process.\n"
-            "    -p  Sort by PSS.\n"
-            "    -u  Sort by USS.\n"
-            "    -m  Sort by mapping order (as read from /proc).\n"
-            "    -h  Hide maps with no RSS.\n",
-            getprogname());
-
-    exit(exit_status);
-}
-
-static void print_separator(std::stringstream& ss) {
-    if (show_wss) {
-        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "-------",
-                                            "-------", "-------", "-------", "-------", "-------",
-                                            "-------", "");
-        return;
-    }
-    ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "-------",
-                                        "-------", "-------", "-------", "-------", "-------",
-                                        "-------", "-------", "");
-}
-
-static void print_header(std::stringstream& ss) {
-    if (show_wss) {
-        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "WRss",
-                                            "WPss", "WUss", "WShCl", "WShDi", "WPrCl", "WPrDi",
-                                            "Name");
-    } else {
-        ss << ::android::base::StringPrintf("%7s  %7s  %7s  %7s  %7s  %7s  %7s  %7s  %s\n", "Vss",
-                                            "Rss", "Pss", "Uss", "ShCl", "ShDi", "PrCl", "PrDi",
-                                            "Name");
-    }
-    print_separator(ss);
-}
-
-static void print_stats(std::stringstream& ss, const MemUsage& stats) {
-    if (!show_wss) {
-        ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", stats.vss / 1024);
-    }
-
-    ss << ::android::base::StringPrintf("%6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64
-                                        "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ",
-                                        stats.rss / 1024, stats.pss / 1024, stats.uss / 1024,
-                                        stats.shared_clean / 1024, stats.shared_dirty / 1024,
-                                        stats.private_clean / 1024, stats.private_dirty / 1024);
-}
-
-static int show(const MemUsage& proc_stats, const std::vector<Vma>& maps) {
-    std::stringstream ss;
-    print_header(ss);
-    for (auto& vma : maps) {
-        const MemUsage& vma_stats = vma.usage;
-        if (hide_zeroes && vma_stats.rss == 0) {
-            continue;
-        }
-        print_stats(ss, vma_stats);
-        ss << vma.name << std::endl;
-    }
-    print_separator(ss);
-    print_stats(ss, proc_stats);
-    ss << "TOTAL" << std::endl;
-    std::cout << ss.str();
-
-    return 0;
-}
-
-int main(int argc, char* argv[]) {
-    int opt;
-    auto pss_sort = [](const Vma& a, const Vma& b) {
-        uint64_t pss_a = a.usage.pss;
-        uint64_t pss_b = b.usage.pss;
-        return pss_a > pss_b;
-    };
-
-    auto uss_sort = [](const Vma& a, const Vma& b) {
-        uint64_t uss_a = a.usage.uss;
-        uint64_t uss_b = b.usage.uss;
-        return uss_a > uss_b;
-    };
-
-    std::function<bool(const Vma& a, const Vma& b)> sort_func = nullptr;
-    while ((opt = getopt(argc, argv, "himpuWw")) != -1) {
-        switch (opt) {
-            case 'h':
-                hide_zeroes = true;
-                break;
-            case 'i':
-                // TODO: libmeminfo doesn't support the flag to chose
-                // between idle page tracking vs clear_refs. So for now,
-                // this flag is unused and the library defaults to using
-                // /proc/<pid>/clear_refs for finding the working set.
-                use_pageidle = true;
-                break;
-            case 'm':
-                // this is the default
-                break;
-            case 'p':
-                sort_func = pss_sort;
-                break;
-            case 'u':
-                sort_func = uss_sort;
-                break;
-            case 'W':
-                reset_wss = true;
-                break;
-            case 'w':
-                show_wss = true;
-                break;
-            case '?':
-                usage(EXIT_SUCCESS);
-            default:
-                usage(EXIT_FAILURE);
-        }
-    }
-
-    if (optind != (argc - 1)) {
-        fprintf(stderr, "Need exactly one pid at the end\n");
-        usage(EXIT_FAILURE);
-    }
-
-    pid_t pid = atoi(argv[optind]);
-    if (pid == 0) {
-        std::cerr << "Invalid process id" << std::endl;
-        exit(EXIT_FAILURE);
-    }
-
-    if (reset_wss) {
-        if (!ProcMemInfo::ResetWorkingSet(pid)) {
-            std::cerr << "Failed to reset working set of pid : " << pid << std::endl;
-            exit(EXIT_FAILURE);
-        }
-        return 0;
-    }
-
-    ProcMemInfo proc(pid, show_wss);
-    const MemUsage& proc_stats = proc.Usage();
-    std::vector<Vma> maps(proc.Maps());
-    if (sort_func != nullptr) {
-        std::sort(maps.begin(), maps.end(), sort_func);
-    }
-
-    return show(proc_stats, maps);
-}
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp
deleted file mode 100644
index 1e44ff9..0000000
--- a/libmeminfo/tools/procrank.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * 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.
- */
-
-#include <android-base/file.h>
-#include <android-base/parseint.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <dirent.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <linux/kernel-page-flags.h>
-#include <linux/oom.h>
-#include <meminfo/procmeminfo.h>
-#include <meminfo/sysmeminfo.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <memory>
-#include <sstream>
-#include <vector>
-
-using ::android::meminfo::MemUsage;
-using ::android::meminfo::ProcMemInfo;
-
-struct ProcessRecord {
-  public:
-    ProcessRecord(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0)
-        : pid_(-1),
-          oomadj_(OOM_SCORE_ADJ_MAX + 1),
-          cmdline_(""),
-          proportional_swap_(0),
-          unique_swap_(0),
-          zswap_(0) {
-        std::unique_ptr<ProcMemInfo> procmem =
-                std::make_unique<ProcMemInfo>(pid, get_wss, pgflags, pgflags_mask);
-        if (procmem == nullptr) {
-            std::cerr << "Failed to create ProcMemInfo for: " << pid << std::endl;
-            return;
-        }
-
-        std::string fname = ::android::base::StringPrintf("/proc/%d/oom_score_adj", pid);
-        auto oomscore_fp =
-                std::unique_ptr<FILE, decltype(&fclose)>{fopen(fname.c_str(), "re"), fclose};
-        if (oomscore_fp == nullptr) {
-            std::cerr << "Failed to open oom_score_adj file: " << fname << std::endl;
-            return;
-        }
-
-        if (fscanf(oomscore_fp.get(), "%d\n", &oomadj_) != 1) {
-            std::cerr << "Failed to read oomadj from: " << fname << std::endl;
-            return;
-        }
-
-        fname = ::android::base::StringPrintf("/proc/%d/cmdline", pid);
-        if (!::android::base::ReadFileToString(fname, &cmdline_)) {
-            std::cerr << "Failed to read cmdline from: " << fname << std::endl;
-            cmdline_ = "<unknown>";
-        }
-        // We deliberately don't read the proc/<pid>cmdline file directly into 'cmdline_'
-        // because of some processes showing up cmdlines that end with "0x00 0x0A 0x00"
-        // e.g. xtra-daemon, lowi-server
-        // The .c_str() assignment below then takes care of trimming the cmdline at the first
-        // 0x00. This is how original procrank worked (luckily)
-        cmdline_.resize(strlen(cmdline_.c_str()));
-        usage_or_wss_ = get_wss ? procmem->Wss() : procmem->Usage();
-        swap_offsets_ = procmem->SwapOffsets();
-        pid_ = pid;
-    }
-
-    bool valid() const { return pid_ != -1; }
-
-    void CalculateSwap(const uint16_t* swap_offset_array, float zram_compression_ratio) {
-        for (auto& off : swap_offsets_) {
-            proportional_swap_ += getpagesize() / swap_offset_array[off];
-            unique_swap_ += swap_offset_array[off] == 1 ? getpagesize() : 0;
-            zswap_ = proportional_swap_ * zram_compression_ratio;
-        }
-    }
-
-    // Getters
-    pid_t pid() const { return pid_; }
-    const std::string& cmdline() const { return cmdline_; }
-    int32_t oomadj() const { return oomadj_; }
-    uint64_t proportional_swap() const { return proportional_swap_; }
-    uint64_t unique_swap() const { return unique_swap_; }
-    uint64_t zswap() const { return zswap_; }
-
-    // Wrappers to ProcMemInfo
-    const std::vector<uint16_t>& SwapOffsets() const { return swap_offsets_; }
-    const MemUsage& Usage() const { return usage_or_wss_; }
-    const MemUsage& Wss() const { return usage_or_wss_; }
-
-  private:
-    pid_t pid_;
-    int32_t oomadj_;
-    std::string cmdline_;
-    uint64_t proportional_swap_;
-    uint64_t unique_swap_;
-    uint64_t zswap_;
-    MemUsage usage_or_wss_;
-    std::vector<uint16_t> swap_offsets_;
-};
-
-// Show working set instead of memory consumption
-bool show_wss = false;
-// Reset working set of each process
-bool reset_wss = false;
-// Show per-process oom_score_adj column
-bool show_oomadj = false;
-// True if the device has swap enabled
-bool has_swap = false;
-// True, if device has zram enabled
-bool has_zram = false;
-// If zram is enabled, the compression ratio is zram used / swap used.
-float zram_compression_ratio = 0.0;
-// Sort process in reverse, default is descending
-bool reverse_sort = false;
-
-// Calculated total memory usage across all processes in the system
-uint64_t total_pss = 0;
-uint64_t total_uss = 0;
-uint64_t total_swap = 0;
-uint64_t total_pswap = 0;
-uint64_t total_uswap = 0;
-uint64_t total_zswap = 0;
-
-[[noreturn]] static void usage(int exit_status) {
-    std::cerr << "Usage: " << getprogname() << " [ -W ] [ -v | -r | -p | -u | -s | -h ]"
-              << std::endl
-              << "    -v  Sort by VSS." << std::endl
-              << "    -r  Sort by RSS." << std::endl
-              << "    -p  Sort by PSS." << std::endl
-              << "    -u  Sort by USS." << std::endl
-              << "    -s  Sort by swap." << std::endl
-              << "        (Default sort order is PSS.)" << std::endl
-              << "    -R  Reverse sort order (default is descending)." << std::endl
-              << "    -c  Only show cached (storage backed) pages" << std::endl
-              << "    -C  Only show non-cached (ram/swap backed) pages" << std::endl
-              << "    -k  Only show pages collapsed by KSM" << std::endl
-              << "    -w  Display statistics for working set only." << std::endl
-              << "    -W  Reset working set of all processes." << std::endl
-              << "    -o  Show and sort by oom score against lowmemorykiller thresholds."
-              << std::endl
-              << "    -h  Display this help screen." << std::endl;
-    exit(exit_status);
-}
-
-static bool read_all_pids(std::vector<pid_t>* pids, std::function<bool(pid_t pid)> for_each_pid) {
-    pids->clear();
-    std::unique_ptr<DIR, int (*)(DIR*)> procdir(opendir("/proc"), closedir);
-    if (!procdir) return false;
-
-    struct dirent* dir;
-    pid_t pid;
-    while ((dir = readdir(procdir.get()))) {
-        if (!::android::base::ParseInt(dir->d_name, &pid)) continue;
-        if (!for_each_pid(pid)) return false;
-        pids->emplace_back(pid);
-    }
-
-    return true;
-}
-
-static bool count_swap_offsets(const ProcessRecord& proc, uint16_t* swap_offset_array,
-                               uint32_t size) {
-    const std::vector<uint16_t>& swp_offs = proc.SwapOffsets();
-    for (auto& off : swp_offs) {
-        if (off >= size) {
-            std::cerr << "swap offset " << off << " is out of bounds for process: " << proc.pid()
-                      << std::endl;
-            return false;
-        }
-
-        if (swap_offset_array[off] == USHRT_MAX) {
-            std::cerr << "swap offset " << off << " ref count overflow in process: " << proc.pid()
-                      << std::endl;
-            return false;
-        }
-
-        swap_offset_array[off]++;
-    }
-
-    return true;
-}
-
-static void print_header(std::stringstream& ss) {
-    ss.str("");
-    ss << ::android::base::StringPrintf("%5s  ", "PID");
-    if (show_oomadj) {
-        ss << ::android::base::StringPrintf("%5s  ", "oom");
-    }
-
-    if (show_wss) {
-        ss << ::android::base::StringPrintf("%7s  %7s  %7s  ", "WRss", "WPss", "WUss");
-        // now swap statistics here, working set pages by definition shouldn't end up in swap.
-    } else {
-        ss << ::android::base::StringPrintf("%8s  %7s  %7s  %7s  ", "Vss", "Rss", "Pss", "Uss");
-        if (has_swap) {
-            ss << ::android::base::StringPrintf("%7s  %7s  %7s  ", "Swap", "PSwap", "USwap");
-            if (has_zram) {
-                ss << ::android::base::StringPrintf("%7s  ", "ZSwap");
-            }
-        }
-    }
-
-    ss << "cmdline";
-}
-
-static void print_process_record(std::stringstream& ss, ProcessRecord& proc) {
-    ss << ::android::base::StringPrintf("%5d  ", proc.pid());
-    if (show_oomadj) {
-        ss << ::android::base::StringPrintf("%5d  ", proc.oomadj());
-    }
-
-    if (show_wss) {
-        ss << ::android::base::StringPrintf("%6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  ",
-                                            proc.Wss().rss / 1024, proc.Wss().pss / 1024,
-                                            proc.Wss().uss / 1024);
-    } else {
-        ss << ::android::base::StringPrintf("%7" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64 "K  %6" PRIu64
-                                            "K  ",
-                                            proc.Usage().vss / 1024, proc.Usage().rss / 1024,
-                                            proc.Usage().pss / 1024, proc.Usage().uss / 1024);
-        if (has_swap) {
-            ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", proc.Usage().swap / 1024);
-            ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", proc.proportional_swap() / 1024);
-            ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", proc.unique_swap() / 1024);
-            if (has_zram) {
-                ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", (proc.zswap() / 1024));
-            }
-        }
-    }
-}
-
-static void print_processes(std::stringstream& ss, std::vector<ProcessRecord>& procs,
-                            uint16_t* swap_offset_array) {
-    for (auto& proc : procs) {
-        total_pss += show_wss ? proc.Wss().pss : proc.Usage().pss;
-        total_uss += show_wss ? proc.Wss().uss : proc.Usage().uss;
-        if (!show_wss && has_swap) {
-            proc.CalculateSwap(swap_offset_array, zram_compression_ratio);
-            total_swap += proc.Usage().swap;
-            total_pswap += proc.proportional_swap();
-            total_uswap += proc.unique_swap();
-            if (has_zram) {
-                total_zswap += proc.zswap();
-            }
-        }
-
-        print_process_record(ss, proc);
-        ss << proc.cmdline() << std::endl;
-    }
-}
-
-static void print_separator(std::stringstream& ss) {
-    ss << ::android::base::StringPrintf("%5s  ", "");
-    if (show_oomadj) {
-        ss << ::android::base::StringPrintf("%5s  ", "");
-    }
-
-    if (show_wss) {
-        ss << ::android::base::StringPrintf("%7s  %7s  %7s  ", "", "------", "------");
-    } else {
-        ss << ::android::base::StringPrintf("%8s  %7s  %7s  %7s  ", "", "", "------", "------");
-        if (has_swap) {
-            ss << ::android::base::StringPrintf("%7s  %7s  %7s  ", "------", "------", "------");
-            if (has_zram) {
-                ss << ::android::base::StringPrintf("%7s  ", "------");
-            }
-        }
-    }
-
-    ss << ::android::base::StringPrintf("%s", "------");
-}
-
-static void print_totals(std::stringstream& ss) {
-    ss << ::android::base::StringPrintf("%5s  ", "");
-    if (show_oomadj) {
-        ss << ::android::base::StringPrintf("%5s  ", "");
-    }
-
-    if (show_wss) {
-        ss << ::android::base::StringPrintf("%7s  %6" PRIu64 "K  %6" PRIu64 "K  ", "",
-                                            total_pss / 1024, total_uss / 1024);
-    } else {
-        ss << ::android::base::StringPrintf("%8s  %7s  %6" PRIu64 "K  %6" PRIu64 "K  ", "", "",
-                                            total_pss / 1024, total_uss / 1024);
-        if (has_swap) {
-            ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", total_swap / 1024);
-            ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", total_pswap / 1024);
-            ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", total_uswap / 1024);
-            if (has_zram) {
-                ss << ::android::base::StringPrintf("%6" PRIu64 "K  ", total_zswap / 1024);
-            }
-        }
-    }
-    ss << "TOTAL";
-}
-
-static void print_sysmeminfo(std::stringstream& ss, ::android::meminfo::SysMemInfo& smi) {
-    if (has_swap) {
-        ss << ::android::base::StringPrintf("ZRAM: %" PRIu64 "K physical used for %" PRIu64
-                                            "K in swap "
-                                            "(%" PRIu64 "K total swap)",
-                                            smi.mem_zram_kb(),
-                                            (smi.mem_swap_kb() - smi.mem_swap_free_kb()),
-                                            smi.mem_swap_kb())
-           << std::endl;
-    }
-
-    ss << ::android::base::StringPrintf(" RAM: %" PRIu64 "K total, %" PRIu64 "K free, %" PRIu64
-                                        "K buffers, "
-                                        "%" PRIu64 "K cached, %" PRIu64 "K shmem, %" PRIu64
-                                        "K slab",
-                                        smi.mem_total_kb(), smi.mem_free_kb(), smi.mem_buffers_kb(),
-                                        smi.mem_cached_kb(), smi.mem_shmem_kb(), smi.mem_slab_kb());
-}
-
-int main(int argc, char* argv[]) {
-    auto pss_sort = [](ProcessRecord& a, ProcessRecord& b) {
-        MemUsage stats_a = show_wss ? a.Wss() : a.Usage();
-        MemUsage stats_b = show_wss ? b.Wss() : b.Usage();
-        return reverse_sort ? stats_a.pss < stats_b.pss : stats_a.pss > stats_b.pss;
-    };
-
-    auto uss_sort = [](ProcessRecord& a, ProcessRecord& b) {
-        MemUsage stats_a = show_wss ? a.Wss() : a.Usage();
-        MemUsage stats_b = show_wss ? b.Wss() : b.Usage();
-        return reverse_sort ? stats_a.uss < stats_b.uss : stats_a.uss > stats_b.uss;
-    };
-
-    auto rss_sort = [](ProcessRecord& a, ProcessRecord& b) {
-        MemUsage stats_a = show_wss ? a.Wss() : a.Usage();
-        MemUsage stats_b = show_wss ? b.Wss() : b.Usage();
-        return reverse_sort ? stats_a.rss < stats_b.rss : stats_a.rss > stats_b.rss;
-    };
-
-    auto vss_sort = [](ProcessRecord& a, ProcessRecord& b) {
-        MemUsage stats_a = show_wss ? a.Wss() : a.Usage();
-        MemUsage stats_b = show_wss ? b.Wss() : b.Usage();
-        return reverse_sort ? stats_a.vss < stats_b.vss : stats_a.vss > stats_b.vss;
-    };
-
-    auto swap_sort = [](ProcessRecord& a, ProcessRecord& b) {
-        MemUsage stats_a = show_wss ? a.Wss() : a.Usage();
-        MemUsage stats_b = show_wss ? b.Wss() : b.Usage();
-        return reverse_sort ? stats_a.swap < stats_b.swap : stats_a.swap > stats_b.swap;
-    };
-
-    auto oomadj_sort = [](ProcessRecord& a, ProcessRecord& b) {
-        return reverse_sort ? a.oomadj() < b.oomadj() : a.oomadj() > b.oomadj();
-    };
-
-    // default PSS sort
-    std::function<bool(ProcessRecord & a, ProcessRecord & b)> proc_sort = pss_sort;
-
-    // count all pages by default
-    uint64_t pgflags = 0;
-    uint64_t pgflags_mask = 0;
-
-    int opt;
-    while ((opt = getopt(argc, argv, "cChkoprRsuvwW")) != -1) {
-        switch (opt) {
-            case 'c':
-                pgflags = 0;
-                pgflags_mask = (1 << KPF_SWAPBACKED);
-                break;
-            case 'C':
-                pgflags = (1 << KPF_SWAPBACKED);
-                pgflags_mask = (1 << KPF_SWAPBACKED);
-                break;
-            case 'h':
-                usage(EXIT_SUCCESS);
-            case 'k':
-                pgflags = (1 << KPF_KSM);
-                pgflags_mask = (1 << KPF_KSM);
-                break;
-            case 'o':
-                proc_sort = oomadj_sort;
-                show_oomadj = true;
-                break;
-            case 'p':
-                proc_sort = pss_sort;
-                break;
-            case 'r':
-                proc_sort = rss_sort;
-                break;
-            case 'R':
-                reverse_sort = true;
-                break;
-            case 's':
-                proc_sort = swap_sort;
-                break;
-            case 'u':
-                proc_sort = uss_sort;
-                break;
-            case 'v':
-                proc_sort = vss_sort;
-                break;
-            case 'w':
-                show_wss = true;
-                break;
-            case 'W':
-                reset_wss = true;
-                break;
-            default:
-                usage(EXIT_FAILURE);
-        }
-    }
-
-    std::vector<pid_t> pids;
-    std::vector<ProcessRecord> procs;
-    if (reset_wss) {
-        if (!read_all_pids(&pids,
-                           [&](pid_t pid) -> bool { return ProcMemInfo::ResetWorkingSet(pid); })) {
-            std::cerr << "Failed to reset working set of all processes" << std::endl;
-            exit(EXIT_FAILURE);
-        }
-        // we are done, all other options passed to procrank are ignored in the presence of '-W'
-        return 0;
-    }
-
-    ::android::meminfo::SysMemInfo smi;
-    if (!smi.ReadMemInfo()) {
-        std::cerr << "Failed to get system memory info" << std::endl;
-        exit(EXIT_FAILURE);
-    }
-
-    // Figure out swap and zram
-    uint64_t swap_total = smi.mem_swap_kb() * 1024;
-    has_swap = swap_total > 0;
-    // Allocate the swap array
-    auto swap_offset_array = std::make_unique<uint16_t[]>(swap_total / getpagesize());
-    if (has_swap) {
-        has_zram = smi.mem_zram_kb() > 0;
-        if (has_zram) {
-            zram_compression_ratio = static_cast<float>(smi.mem_zram_kb()) /
-                                     (smi.mem_swap_kb() - smi.mem_swap_free_kb());
-        }
-    }
-
-    auto mark_swap_usage = [&](pid_t pid) -> bool {
-        ProcessRecord proc(pid, show_wss, pgflags, pgflags_mask);
-        if (!proc.valid()) {
-            // Check to see if the process is still around, skip the process if the proc
-            // directory is inaccessible. It was most likely killed while creating the process
-            // record
-            std::string procdir = ::android::base::StringPrintf("/proc/%d", pid);
-            if (access(procdir.c_str(), F_OK | R_OK)) return true;
-
-            // Warn if we failed to gather process stats even while it is still alive.
-            // Return success here, so we continue to print stats for other processes.
-            std::cerr << "warning: failed to create process record for: " << pid << std::endl;
-            return true;
-        }
-
-        // Skip processes with no memory mappings
-        uint64_t vss = show_wss ? proc.Wss().vss : proc.Usage().vss;
-        if (vss == 0) return true;
-
-        // collect swap_offset counts from all processes in 1st pass
-        if (!show_wss && has_swap &&
-            !count_swap_offsets(proc, swap_offset_array.get(), swap_total / getpagesize())) {
-            std::cerr << "Failed to count swap offsets for process: " << pid << std::endl;
-            return false;
-        }
-
-        procs.emplace_back(std::move(proc));
-        return true;
-    };
-
-    // Get a list of all pids currently running in the system in 1st pass through all processes.
-    // Mark each swap offset used by the process as we find them for calculating proportional
-    // swap usage later.
-    if (!read_all_pids(&pids, mark_swap_usage)) {
-        std::cerr << "Failed to read all pids from the system" << std::endl;
-        exit(EXIT_FAILURE);
-    }
-
-    std::stringstream ss;
-    if (procs.empty()) {
-        // This would happen in corner cases where procrank is being run to find KSM usage on a
-        // system with no KSM and combined with working set determination as follows
-        //   procrank -w -u -k
-        //   procrank -w -s -k
-        //   procrank -w -o -k
-        ss << "<empty>" << std::endl << std::endl;
-        print_sysmeminfo(ss, smi);
-        ss << std::endl;
-        std::cout << ss.str();
-        return 0;
-    }
-
-    // Sort all process records, default is PSS descending
-    std::sort(procs.begin(), procs.end(), proc_sort);
-
-    // start dumping output in string stream
-    print_header(ss);
-    ss << std::endl;
-
-    // 2nd pass to calculate and get per process stats to add them up
-    print_processes(ss, procs, swap_offset_array.get());
-
-    // Add separator to output
-    print_separator(ss);
-    ss << std::endl;
-
-    // Add totals to output
-    print_totals(ss);
-    ss << std::endl << std::endl;
-
-    // Add system information at the end
-    print_sysmeminfo(ss, smi);
-    ss << std::endl;
-
-    // dump on the screen
-    std::cout << ss.str();
-
-    return 0;
-}
diff --git a/libmeminfo/tools/showmap.cpp b/libmeminfo/tools/showmap.cpp
deleted file mode 100644
index a80fa76..0000000
--- a/libmeminfo/tools/showmap.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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 <getopt.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <meminfo/procmeminfo.h>
-
-using ::android::meminfo::Vma;
-
-struct VmaInfo {
-    Vma vma;
-    bool is_bss;
-    uint32_t count;
-
-    VmaInfo() = default;
-    VmaInfo(const Vma& v) : vma(v), is_bss(false), count(1) {}
-    VmaInfo(const Vma& v, bool bss) : vma(v), is_bss(bss), count(1) {}
-    VmaInfo(const Vma& v, const std::string& name, bool bss) : vma(v), is_bss(bss), count(1) {
-        vma.name = name;
-    }
-};
-
-// Global options
-static std::string g_filename = "";
-static bool g_merge_by_names = false;
-static bool g_terse = false;
-static bool g_verbose = false;
-static bool g_show_addr = false;
-static bool g_quiet = false;
-static pid_t g_pid = -1;
-
-static VmaInfo g_total;
-static std::vector<VmaInfo> g_vmas;
-
-[[noreturn]] static void usage(int exit_status) {
-    fprintf(stderr,
-            "%s [-aqtv] [-f FILE] PID\n"
-            "-a\taddresses (show virtual memory map)\n"
-            "-q\tquiet (don't show error if map could not be read)\n"
-            "-t\tterse (show only items with private pages)\n"
-            "-v\tverbose (don't coalesce maps with the same name)\n"
-            "-f\tFILE (read from input from FILE instead of PID)\n",
-            getprogname());
-
-    exit(exit_status);
-}
-
-static bool is_library(const std::string& name) {
-    return (name.size() > 4) && (name[0] == '/') && ::android::base::EndsWith(name, ".so");
-}
-
-static bool insert_before(const VmaInfo& a, const VmaInfo& b) {
-    if (g_show_addr) {
-        return (a.vma.start < b.vma.start || (a.vma.start == b.vma.start && a.vma.end < b.vma.end));
-    }
-
-    return strcmp(a.vma.name.c_str(), b.vma.name.c_str()) < 0;
-}
-
-static void collect_vma(const Vma& vma) {
-    if (g_vmas.empty()) {
-        g_vmas.emplace_back(vma);
-        return;
-    }
-
-    VmaInfo current(vma);
-    VmaInfo& last = g_vmas.back();
-    // determine if this is bss;
-    if (vma.name.empty()) {
-        if (last.vma.end == current.vma.start && is_library(last.vma.name)) {
-            current.vma.name = last.vma.name;
-            current.is_bss = true;
-        } else {
-            current.vma.name = "[anon]";
-        }
-    }
-
-    std::vector<VmaInfo>::iterator it;
-    for (it = g_vmas.begin(); it != g_vmas.end(); it++) {
-        if (g_merge_by_names && (it->vma.name == current.vma.name)) {
-            it->vma.usage.vss += current.vma.usage.vss;
-            it->vma.usage.rss += current.vma.usage.rss;
-            it->vma.usage.pss += current.vma.usage.pss;
-
-            it->vma.usage.shared_clean += current.vma.usage.shared_clean;
-            it->vma.usage.shared_dirty += current.vma.usage.shared_dirty;
-            it->vma.usage.private_clean += current.vma.usage.private_clean;
-            it->vma.usage.private_dirty += current.vma.usage.private_dirty;
-            it->vma.usage.swap += current.vma.usage.swap;
-            it->vma.usage.swap_pss += current.vma.usage.swap_pss;
-            it->is_bss &= current.is_bss;
-            it->count++;
-            break;
-        }
-
-        if (insert_before(current, *it)) {
-            g_vmas.insert(it, current);
-            break;
-        }
-    }
-
-    if (it == g_vmas.end()) {
-        g_vmas.emplace_back(current);
-    }
-}
-
-static void print_header() {
-    const char* addr1 = g_show_addr ? "           start              end " : "";
-    const char* addr2 = g_show_addr ? "            addr             addr " : "";
-
-    printf("%s virtual                     shared   shared  private  private\n", addr1);
-    printf("%s    size      RSS      PSS    clean    dirty    clean    dirty     swap  swapPSS",
-           addr2);
-    if (!g_verbose && !g_show_addr) {
-        printf("   # ");
-    }
-    printf(" object\n");
-}
-
-static void print_divider() {
-    if (g_show_addr) {
-        printf("-------- -------- ");
-    }
-    printf("-------- -------- -------- -------- -------- -------- -------- -------- -------- ");
-    if (!g_verbose && !g_show_addr) {
-        printf("---- ");
-    }
-    printf("------------------------------\n");
-}
-
-static void print_vmainfo(const VmaInfo& v, bool total) {
-    if (g_show_addr) {
-        if (total) {
-            printf("                                  ");
-        } else {
-            printf("%16" PRIx64 " %16" PRIx64 " ", v.vma.start, v.vma.end);
-        }
-    }
-    printf("%8" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64
-           " %8" PRIu64 " %8" PRIu64 " ",
-           v.vma.usage.vss, v.vma.usage.rss, v.vma.usage.pss, v.vma.usage.shared_clean,
-           v.vma.usage.shared_dirty, v.vma.usage.private_clean, v.vma.usage.private_dirty,
-           v.vma.usage.swap, v.vma.usage.swap_pss);
-    if (!g_verbose && !g_show_addr) {
-        printf("%4" PRIu32 " ", v.count);
-    }
-}
-
-static int showmap(void) {
-    if (!::android::meminfo::ForEachVmaFromFile(g_filename, collect_vma)) {
-        if (!g_quiet) {
-            fprintf(stderr, "Failed to parse file %s\n", g_filename.c_str());
-        }
-        return 1;
-    }
-
-    print_header();
-    print_divider();
-
-    for (const auto& v : g_vmas) {
-        g_total.vma.usage.vss += v.vma.usage.vss;
-        g_total.vma.usage.rss += v.vma.usage.rss;
-        g_total.vma.usage.pss += v.vma.usage.pss;
-
-        g_total.vma.usage.private_clean += v.vma.usage.private_clean;
-        g_total.vma.usage.private_dirty += v.vma.usage.private_dirty;
-        g_total.vma.usage.shared_clean += v.vma.usage.shared_clean;
-        g_total.vma.usage.shared_dirty += v.vma.usage.shared_dirty;
-
-        g_total.vma.usage.swap += v.vma.usage.swap;
-        g_total.vma.usage.swap_pss += v.vma.usage.swap_pss;
-        g_total.count += v.count;
-
-        if (g_terse && !(v.vma.usage.private_dirty || v.vma.usage.private_clean)) {
-            continue;
-        }
-
-        print_vmainfo(v, false);
-        printf("%s%s\n", v.vma.name.c_str(), v.is_bss ? " [bss]" : "");
-    }
-
-    print_divider();
-    print_header();
-    print_divider();
-
-    print_vmainfo(g_total, true);
-    printf("TOTAL\n");
-
-    return 0;
-}
-
-int main(int argc, char* argv[]) {
-    signal(SIGPIPE, SIG_IGN);
-    struct option longopts[] = {
-            {"help", no_argument, nullptr, 'h'},
-            {0, 0, nullptr, 0},
-    };
-
-    int opt;
-    while ((opt = getopt_long(argc, argv, "tvaqf:h", longopts, nullptr)) != -1) {
-        switch (opt) {
-            case 't':
-                g_terse = true;
-                break;
-            case 'a':
-                g_show_addr = true;
-                break;
-            case 'v':
-                g_verbose = true;
-                break;
-            case 'q':
-                g_quiet = true;
-                break;
-            case 'f':
-                g_filename = optarg;
-                break;
-            case 'h':
-                usage(EXIT_SUCCESS);
-            default:
-                usage(EXIT_FAILURE);
-        }
-    }
-
-    if (g_filename.empty()) {
-        if ((argc - 1) < optind) {
-            fprintf(stderr, "Invalid arguments: Must provide <pid> at the end\n");
-            usage(EXIT_FAILURE);
-        }
-
-        g_pid = atoi(argv[optind]);
-        if (g_pid <= 0) {
-            fprintf(stderr, "Invalid process id %s\n", argv[optind]);
-            usage(EXIT_FAILURE);
-        }
-
-        g_filename = ::android::base::StringPrintf("/proc/%d/smaps", g_pid);
-    }
-
-    g_merge_by_names = !g_verbose && !g_show_addr;
-    return showmap();
-}
diff --git a/libmeminfo/tools/wsstop.cpp b/libmeminfo/tools/wsstop.cpp
deleted file mode 100644
index 368d04e..0000000
--- a/libmeminfo/tools/wsstop.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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 <getopt.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <meminfo/pageacct.h>
-#include <meminfo/procmeminfo.h>
-
-using ::android::meminfo::ProcMemInfo;
-using ::android::meminfo::Vma;
-
-// Global options
-static int32_t g_delay = 0;
-static int32_t g_total = 2;
-static pid_t g_pid = -1;
-
-[[noreturn]] static void usage(int exit_status) {
-    fprintf(stderr,
-            "%s [-d DELAY_BETWEEN_EACH_SAMPLE] [-n REFRESH_TOTAL] PID\n"
-            "-d\tdelay between each working set sample (default 0)\n"
-            "-n\ttotal number of refreshes before we exit (default 2)\n",
-            getprogname());
-
-    exit(exit_status);
-}
-
-static void print_header() {
-    const char* addr1 = "           start              end ";
-    const char* addr2 = "            addr             addr ";
-
-    printf("%s  virtual                        shared    shared   private   private\n", addr1);
-    printf("%s     size       RSS       PSS     clean     dirty     clean     dirty      swap   "
-           "swapPSS",
-           addr2);
-    printf(" object\n");
-}
-
-static void print_divider() {
-    printf("---------------- ---------------- ");
-    printf("--------- --------- --------- --------- --------- --------- --------- --------- "
-           "--------- ");
-    printf("------------------------------\n");
-}
-
-static void print_vma(const Vma& v) {
-    printf("%16" PRIx64 " %16" PRIx64 " ", v.start, v.end);
-    printf("%8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64
-           "K %8" PRIu64 "K %8" PRIu64 "K %8" PRIu64 "K ",
-           v.usage.vss / 1024, v.usage.rss / 1024, v.usage.pss / 1024, v.usage.shared_clean / 1024,
-           v.usage.shared_dirty / 1024, v.usage.private_clean / 1024, v.usage.private_dirty / 1024,
-           v.usage.swap / 1024, v.usage.swap_pss / 1024);
-    printf("%s\n", v.name.c_str());
-}
-
-static bool same_vma(const Vma& cur, const Vma& last) {
-    return (cur.start == last.start && cur.end == last.end && cur.name == last.name &&
-            cur.flags == last.flags && cur.offset == last.offset);
-}
-
-static Vma diff_vma_params(const Vma& cur, const Vma& last) {
-    Vma res;
-    res.usage.shared_clean = cur.usage.shared_clean > last.usage.shared_clean
-                                     ? cur.usage.shared_clean - last.usage.shared_clean
-                                     : 0;
-    res.usage.shared_dirty = cur.usage.shared_dirty > last.usage.shared_dirty
-                                     ? cur.usage.shared_dirty - last.usage.shared_dirty
-                                     : 0;
-    res.usage.private_clean = cur.usage.private_clean > last.usage.private_clean
-                                      ? cur.usage.private_clean - last.usage.private_clean
-                                      : 0;
-    res.usage.private_dirty = cur.usage.private_dirty > last.usage.private_dirty
-                                      ? cur.usage.private_dirty - last.usage.private_dirty
-                                      : 0;
-
-    res.usage.rss = cur.usage.rss > last.usage.rss ? cur.usage.rss - last.usage.rss : 0;
-    res.usage.pss = cur.usage.pss > last.usage.pss ? cur.usage.pss - last.usage.pss : 0;
-    res.usage.uss = cur.usage.uss > last.usage.uss ? cur.usage.uss - last.usage.uss : 0;
-    res.usage.swap = cur.usage.swap > last.usage.swap ? cur.usage.swap - last.usage.swap : 0;
-    res.usage.swap_pss =
-            cur.usage.swap_pss > last.usage.swap_pss ? cur.usage.swap_pss - last.usage.swap_pss : 0;
-
-    // set vma properties to the same as the current one.
-    res.start = cur.start;
-    res.end = cur.end;
-    res.offset = cur.offset;
-    res.flags = cur.flags;
-    res.name = cur.name;
-    return res;
-}
-
-static void diff_workingset(std::vector<Vma>& wss, std::vector<Vma>& old, std::vector<Vma>* res) {
-    res->clear();
-    auto vma_sorter = [](const Vma& a, const Vma& b) { return a.start < b.start; };
-    std::sort(wss.begin(), wss.end(), vma_sorter);
-    std::sort(old.begin(), old.end(), vma_sorter);
-    if (old.empty()) {
-        *res = wss;
-        return;
-    }
-
-    for (auto& i : wss) {
-        bool found_same_vma = false;
-        // TODO: This is highly inefficient, fix it if it takes
-        // too long. Worst case will be system_server
-        for (auto& j : old) {
-            if (same_vma(i, j)) {
-                res->emplace_back(diff_vma_params(i, j));
-                found_same_vma = true;
-                break;
-            }
-        }
-
-        if (!found_same_vma) {
-            res->emplace_back(i);
-        }
-    }
-
-    std::sort(res->begin(), res->end(), vma_sorter);
-    return;
-}
-
-static int workingset() {
-    std::vector<Vma> last_wss = {};
-    std::vector<Vma> diff_wss = {};
-    uint32_t nr_refresh = 0;
-
-    while (true) {
-        std::unique_ptr<ProcMemInfo> proc_mem = std::make_unique<ProcMemInfo>(g_pid, true);
-        std::vector<Vma> wss = proc_mem->MapsWithPageIdle();
-
-        diff_workingset(wss, last_wss, &diff_wss);
-        diff_wss.erase(std::remove_if(diff_wss.begin(), diff_wss.end(),
-                                      [](const auto& v) { return v.usage.rss == 0; }),
-                       diff_wss.end());
-        if ((nr_refresh % 5) == 0) {
-            print_header();
-            print_divider();
-        }
-
-        for (const auto& v : diff_wss) {
-            print_vma(v);
-        }
-
-        nr_refresh++;
-        if (nr_refresh == g_total) {
-            break;
-        }
-
-        last_wss = wss;
-        sleep(g_delay);
-        print_divider();
-    }
-
-    return 0;
-}
-
-int main(int argc, char* argv[]) {
-    struct option longopts[] = {
-            {"help", no_argument, nullptr, 'h'},
-            {0, 0, nullptr, 0},
-    };
-
-    int opt;
-    while ((opt = getopt_long(argc, argv, "d:n:h", longopts, nullptr)) != -1) {
-        switch (opt) {
-            case 'd':
-                g_delay = atoi(optarg);
-                break;
-            case 'n':
-                g_total = atoi(optarg);
-                break;
-            case 'h':
-                usage(EXIT_SUCCESS);
-            default:
-                usage(EXIT_FAILURE);
-        }
-    }
-
-    if ((argc - 1) < optind) {
-        fprintf(stderr, "Invalid arguments: Must provide <pid> at the end\n");
-        usage(EXIT_FAILURE);
-    }
-
-    g_pid = atoi(argv[optind]);
-    if (g_pid <= 0) {
-        fprintf(stderr, "Invalid process id %s\n", argv[optind]);
-        usage(EXIT_FAILURE);
-    }
-
-    if (!::android::meminfo::PageAcct::KernelHasPageIdle()) {
-        fprintf(stderr, "Missing support for Idle page tracking in the kernel\n");
-        return 0;
-    }
-
-    return workingset();
-}
diff --git a/libmeminfo/vts/Android.mk b/libmeminfo/vts/Android.mk
deleted file mode 100644
index 62d68d9..0000000
--- a/libmeminfo/vts/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := VtsKernelMemInfoTest
--include test/vts/tools/build/Android.host_config.mk
diff --git a/libmeminfo/vts/AndroidTest.xml b/libmeminfo/vts/AndroidTest.xml
deleted file mode 100644
index 9614025..0000000
--- a/libmeminfo/vts/AndroidTest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Config for VTS VtsKernelMemInfoTest.">
-    <option name="config-descriptor:metadata" key="plan" value="vts-kernel" />
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
-        <option name="abort-on-push-failure" value="false"/>
-        <option name="push-group" value="HostDrivenTest.push"/>
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
-        <option name="test-module-name" value="VtsKernelMemInfoTest"/>
-        <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_meminfo_test/vts_meminfo_test" />
-        <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_meminfo_test/vts_meminfo_test" />
-        <option name="binary-test-type" value="gtest"/>
-        <option name="precondition-first-api-level" value="29" />
-        <option name="test-timeout" value="10m"/>
-    </test>
-</configuration>
diff --git a/libmemtrack/.clang-format b/libmemtrack/.clang-format
deleted file mode 120000
index 1af4f51..0000000
--- a/libmemtrack/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-4
\ No newline at end of file
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
deleted file mode 100644
index 4e4554a..0000000
--- a/libmemtrack/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2013 The Android Open Source Project
-
-cc_library_shared {
-    name: "libmemtrack",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
-    srcs: ["memtrack.cpp"],
-    export_include_dirs: ["include"],
-    local_include_dirs: ["include"],
-    include_dirs: ["hardware/libhardware/include"],
-    shared_libs: [
-        "libhardware",
-        "liblog",
-        "libbase",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libutils",
-        "android.hardware.memtrack@1.0",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-}
-
-cc_binary {
-    name: "memtrack_test",
-    srcs: ["memtrack_test.cpp"],
-    static_libs: ["libc++fs"],
-    shared_libs: [
-        "libbase",
-        "libmemtrack",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-}
diff --git a/libmemtrack/OWNERS b/libmemtrack/OWNERS
deleted file mode 100644
index 70b375f..0000000
--- a/libmemtrack/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ccross@google.com
diff --git a/libmemtrack/include/memtrack/memtrack.h b/libmemtrack/include/memtrack/memtrack.h
deleted file mode 100644
index 2134a6f..0000000
--- a/libmemtrack/include/memtrack/memtrack.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2013 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 _LIBMEMTRACK_MEMTRACK_H_
-#define _LIBMEMTRACK_MEMTRACK_H_
-
-#include <sys/types.h>
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * struct memtrack_proc
- *
- * an opaque handle to the memory stats on a process.
- * Created with memtrack_proc_new, destroyed by
- * memtrack_proc_destroy.  Can be reused multiple times with
- * memtrack_proc_get.
- */
-struct memtrack_proc;
-
-/**
- * memtrack_proc_new
- *
- * Return a new handle to hold process memory stats.
- *
- * Returns NULL on error.
- */
-struct memtrack_proc *memtrack_proc_new(void);
-
-/**
- * memtrack_proc_destroy
- *
- * Free all memory associated with a process memory stats handle.
- */
-void memtrack_proc_destroy(struct memtrack_proc *p);
-
-/**
- * memtrack_proc_get
- *
- * Fill a process memory stats handle with data about the given pid.  Can be
- * called on a handle that was just allocated with memtrack_proc_new,
- * or on a handle that has been previously passed to memtrack_proc_get
- * to replace the data with new data on the same or another process.  It is
- * expected that the second call on the same handle should not require
- * allocating any new memory.
- *
- * Returns 0 on success, -errno on error.
- */
-int memtrack_proc_get(struct memtrack_proc *p, pid_t pid);
-
-/**
- * memtrack_proc_graphics_total
- *
- * Return total amount of memory that has been allocated for use as window
- * buffers.  Does not differentiate between memory that has already been
- * accounted for by reading /proc/pid/smaps and memory that has not been
- * accounted for.
- *
- * Returns non-negative size in bytes on success, -errno on error.
- */
-ssize_t memtrack_proc_graphics_total(struct memtrack_proc *p);
-
-/**
- * memtrack_proc_graphics_pss
- *
- * Return total amount of memory that has been allocated for use as window
- * buffers, but has not already been accounted for by reading /proc/pid/smaps.
- * Memory that is shared across processes may already be divided by the
- * number of processes that share it (preferred), or may be charged in full to
- * every process that shares it, depending on the capabilities of the driver.
- *
- * Returns non-negative size in bytes on success, -errno on error.
- */
-ssize_t memtrack_proc_graphics_pss(struct memtrack_proc *p);
-
-/**
- * memtrack_proc_gl_total
- *
- * Same as memtrack_proc_graphics_total, but counts GL memory (which
- * should not overlap with graphics memory) instead of graphics memory.
- *
- * Returns non-negative size in bytes on success, -errno on error.
- */
-ssize_t memtrack_proc_gl_total(struct memtrack_proc *p);
-
-/**
- * memtrack_proc_gl_pss
- *
- * Same as memtrack_proc_graphics_total, but counts GL memory (which
- * should not overlap with graphics memory) instead of graphics memory.
- *
- * Returns non-negative size in bytes on success, -errno on error.
- */
-ssize_t memtrack_proc_gl_pss(struct memtrack_proc *p);
-
-/**
- * memtrack_proc_other_total
- *
- * Same as memtrack_proc_graphics_total, but counts miscellaneous memory
- * not tracked by gl or graphics calls above.
- *
- * Returns non-negative size in bytes on success, -errno on error.
- */
-ssize_t memtrack_proc_other_total(struct memtrack_proc *p);
-
-/**
- * memtrack_proc_other_pss
- *
- * Same as memtrack_proc_graphics_total, but counts miscellaneous memory
- * not tracked by gl or graphics calls above.
- *
- * Returns non-negative size in bytes on success, -errno on error.
- */
-ssize_t memtrack_proc_other_pss(struct memtrack_proc *p);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/libmemtrack/memtrack.cpp b/libmemtrack/memtrack.cpp
deleted file mode 100644
index c5e74c1..0000000
--- a/libmemtrack/memtrack.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2013 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 "memtrack"
-#include <android/hardware/memtrack/1.0/IMemtrack.h>
-#include <memtrack/memtrack.h>
-
-#include <errno.h>
-#include <malloc.h>
-#include <vector>
-#include <string.h>
-#include <mutex>
-
-#include <log/log.h>
-
-using android::hardware::memtrack::V1_0::IMemtrack;
-using android::hardware::memtrack::V1_0::MemtrackType;
-using android::hardware::memtrack::V1_0::MemtrackRecord;
-using android::hardware::memtrack::V1_0::MemtrackFlag;
-using android::hardware::memtrack::V1_0::MemtrackStatus;
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-
-struct memtrack_proc_type {
-    MemtrackType type;
-    std::vector<MemtrackRecord> records;
-};
-
-struct memtrack_proc {
-    pid_t pid;
-    memtrack_proc_type types[static_cast<int>(MemtrackType::NUM_TYPES)];
-};
-
-//TODO(b/31632518)
-static android::sp<IMemtrack> get_instance() {
-    static android::sp<IMemtrack> module = IMemtrack::getService();
-    if (module == nullptr) {
-        ALOGE("Couldn't load memtrack module");
-    }
-    return module;
-}
-
-memtrack_proc *memtrack_proc_new(void)
-{
-    return new memtrack_proc();
-}
-
-void memtrack_proc_destroy(memtrack_proc *p)
-{
-    delete(p);
-}
-
-static int memtrack_proc_get_type(memtrack_proc_type *t,
-        pid_t pid, MemtrackType type)
-{
-    int err = 0;
-    android::sp<IMemtrack> memtrack = get_instance();
-    if (memtrack == nullptr)
-        return -1;
-
-    Return<void> ret = memtrack->getMemory(pid, type,
-        [&t, &err](MemtrackStatus status, hidl_vec<MemtrackRecord> records) {
-            if (status != MemtrackStatus::SUCCESS) {
-                err = -1;
-                t->records.resize(0);
-            }
-            t->records.resize(records.size());
-            for (size_t i = 0; i < records.size(); i++) {
-                t->records[i].sizeInBytes = records[i].sizeInBytes;
-                t->records[i].flags = records[i].flags;
-            }
-    });
-    return ret.isOk() ? err : -1;
-}
-
-/* TODO: sanity checks on return values from HALs:
- *   make sure no records have invalid flags set
- *    - unknown flags
- *    - too many flags of a single category
- *    - missing ACCOUNTED/UNACCOUNTED
- *   make sure there are not overlapping SHARED and SHARED_PSS records
- */
-static int memtrack_proc_sanity_check(memtrack_proc* /*p*/)
-{
-    return 0;
-}
-
-int memtrack_proc_get(memtrack_proc *p, pid_t pid)
-{
-    if (!p) {
-        return -EINVAL;
-    }
-
-    p->pid = pid;
-    for (uint32_t i = 0; i < (uint32_t)MemtrackType::NUM_TYPES; i++) {
-        int ret = memtrack_proc_get_type(&p->types[i], pid, (MemtrackType)i);
-        if (ret != 0)
-           return ret;
-    }
-
-    return memtrack_proc_sanity_check(p);
-}
-
-static ssize_t memtrack_proc_sum(memtrack_proc *p,
-        const std::vector<MemtrackType>& types, uint32_t flags)
-{
-    ssize_t sum = 0;
-
-    for (size_t i = 0; i < types.size(); i++) {
-        memtrack_proc_type type = p->types[static_cast<int>(types[i])];
-        std::vector<MemtrackRecord> records = type.records;
-        for (size_t j = 0; j < records.size(); j++) {
-            if ((records[j].flags & flags) == flags) {
-                sum += records[j].sizeInBytes;
-            }
-        }
-    }
-
-    return sum;
-}
-
-ssize_t memtrack_proc_graphics_total(memtrack_proc *p)
-{
-    std::vector<MemtrackType> types = {MemtrackType::GRAPHICS};
-    return memtrack_proc_sum(p, types, 0);
-}
-
-ssize_t memtrack_proc_graphics_pss(memtrack_proc *p)
-{
-    std::vector<MemtrackType> types = { MemtrackType::GRAPHICS };
-    return memtrack_proc_sum(p, types,
-            (uint32_t)MemtrackFlag::SMAPS_UNACCOUNTED);
-}
-
-ssize_t memtrack_proc_gl_total(memtrack_proc *p)
-{
-    std::vector<MemtrackType> types = { MemtrackType::GL };
-    return memtrack_proc_sum(p, types, 0);
-}
-
-ssize_t memtrack_proc_gl_pss(memtrack_proc *p)
-{
-    std::vector<MemtrackType> types = { MemtrackType::GL };
-    return memtrack_proc_sum(p, types,
-            (uint32_t)MemtrackFlag::SMAPS_UNACCOUNTED);
-}
-
-ssize_t memtrack_proc_other_total(memtrack_proc *p)
-{
-    std::vector<MemtrackType> types = { MemtrackType::MULTIMEDIA,
-            MemtrackType::CAMERA, MemtrackType::OTHER };
-    return memtrack_proc_sum(p, types, 0);
-}
-
-ssize_t memtrack_proc_other_pss(memtrack_proc *p)
-{
-    std::vector<MemtrackType> types = { MemtrackType::MULTIMEDIA,
-            MemtrackType::CAMERA, MemtrackType::OTHER };
-    return memtrack_proc_sum(p, types,
-            (uint32_t)MemtrackFlag::SMAPS_UNACCOUNTED);
-}
diff --git a/libmemtrack/memtrack_test.cpp b/libmemtrack/memtrack_test.cpp
deleted file mode 100644
index aeeaf24..0000000
--- a/libmemtrack/memtrack_test.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <filesystem>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/parseint.h>
-#include <android-base/stringprintf.h>
-#include <memtrack/memtrack.h>
-
-#define DIV_ROUND_UP(x, y) (((x) + (y)-1) / (y))
-
-static void getprocname(pid_t pid, std::string* name) {
-    std::string fname = ::android::base::StringPrintf("/proc/%d/cmdline", pid);
-    if (!::android::base::ReadFileToString(fname, name)) {
-        fprintf(stderr, "Failed to read cmdline from: %s\n", fname.c_str());
-        *name = "<unknown>";
-    }
-}
-
-int main(int /* argc */, char** /* argv */) {
-    int ret;
-    struct memtrack_proc* p;
-    std::vector<pid_t> pids;
-
-    p = memtrack_proc_new();
-    if (p == nullptr) {
-        fprintf(stderr, "failed to create memtrack process handle\n");
-        exit(EXIT_FAILURE);
-    }
-
-    for (auto& de : std::filesystem::directory_iterator("/proc")) {
-        if (!std::filesystem::is_directory(de.status())) {
-            continue;
-        }
-
-        pid_t pid;
-        if (!::android::base::ParseInt(de.path().filename().string(), &pid)) {
-            continue;
-        }
-        pids.emplace_back(pid);
-    }
-
-    for (auto& pid : pids) {
-        size_t v1;
-        size_t v2;
-        size_t v3;
-        size_t v4;
-        size_t v5;
-        size_t v6;
-        std::string cmdline;
-
-        getprocname(pid, &cmdline);
-
-        ret = memtrack_proc_get(p, pid);
-        if (ret) {
-            fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n", pid, strerror(-ret),
-                    ret);
-            continue;
-        }
-
-        v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024);
-        v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024);
-        v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024);
-        v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024);
-        v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024);
-        v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024);
-
-        if (v1 | v2 | v3 | v4 | v5 | v6) {
-            fprintf(stdout, "%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid, v1, v2, v3, v4, v5, v6,
-                    cmdline.c_str());
-        }
-    }
-
-    memtrack_proc_destroy(p);
-
-    return ret;
-}
diff --git a/libmemunreachable/.clang-format b/libmemunreachable/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libmemunreachable/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libmemunreachable/Allocator.cpp b/libmemunreachable/Allocator.cpp
deleted file mode 100644
index 1eb7e98..0000000
--- a/libmemunreachable/Allocator.cpp
+++ /dev/null
@@ -1,468 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// Header page:
-//
-// For minimum allocation size (8 bytes), bitmap can store used allocations for
-// up to 4032*8*8=258048, which is 256KiB minus the header page
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include <sys/cdefs.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-
-#include <cmath>
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <mutex>
-
-#include "android-base/macros.h"
-
-#include "Allocator.h"
-#include "LinkedList.h"
-
-namespace android {
-
-// runtime interfaces used:
-// abort
-// assert - fprintf + mmap
-// mmap
-// munmap
-// prctl
-
-constexpr size_t const_log2(size_t n, size_t p = 0) {
-  return (n <= 1) ? p : const_log2(n / 2, p + 1);
-}
-
-constexpr unsigned int div_round_up(unsigned int x, unsigned int y) {
-  return (x + y - 1) / y;
-}
-
-static constexpr size_t kPageSize = 4096;
-static constexpr size_t kChunkSize = 256 * 1024;
-static constexpr size_t kUsableChunkSize = kChunkSize - kPageSize;
-static constexpr size_t kMaxBucketAllocationSize = kChunkSize / 4;
-static constexpr size_t kMinBucketAllocationSize = 8;
-static constexpr unsigned int kNumBuckets =
-    const_log2(kMaxBucketAllocationSize) - const_log2(kMinBucketAllocationSize) + 1;
-static constexpr unsigned int kUsablePagesPerChunk = kUsableChunkSize / kPageSize;
-
-std::atomic<int> heap_count;
-
-class Chunk;
-
-class HeapImpl {
- public:
-  HeapImpl();
-  ~HeapImpl();
-  void* operator new(std::size_t count) noexcept;
-  void operator delete(void* ptr);
-
-  void* Alloc(size_t size);
-  void Free(void* ptr);
-  bool Empty();
-
-  void MoveToFullList(Chunk* chunk, int bucket_);
-  void MoveToFreeList(Chunk* chunk, int bucket_);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(HeapImpl);
-
-  LinkedList<Chunk*> free_chunks_[kNumBuckets];
-  LinkedList<Chunk*> full_chunks_[kNumBuckets];
-
-  void MoveToList(Chunk* chunk, LinkedList<Chunk*>* head);
-  void* MapAlloc(size_t size);
-  void MapFree(void* ptr);
-  void* AllocLocked(size_t size);
-  void FreeLocked(void* ptr);
-
-  struct MapAllocation {
-    void* ptr;
-    size_t size;
-    MapAllocation* next;
-  };
-  MapAllocation* map_allocation_list_;
-  std::mutex m_;
-};
-
-// Integer log 2, rounds down
-static inline unsigned int log2(size_t n) {
-  return 8 * sizeof(unsigned long long) - __builtin_clzll(n) - 1;
-}
-
-static inline unsigned int size_to_bucket(size_t size) {
-  if (size < kMinBucketAllocationSize) return kMinBucketAllocationSize;
-  return log2(size - 1) + 1 - const_log2(kMinBucketAllocationSize);
-}
-
-static inline size_t bucket_to_size(unsigned int bucket) {
-  return kMinBucketAllocationSize << bucket;
-}
-
-static void* MapAligned(size_t size, size_t align) {
-  const int prot = PROT_READ | PROT_WRITE;
-  const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
-
-  size = (size + kPageSize - 1) & ~(kPageSize - 1);
-
-  // Over-allocate enough to align
-  size_t map_size = size + align - kPageSize;
-  if (map_size < size) {
-    return nullptr;
-  }
-
-  void* ptr = mmap(NULL, map_size, prot, flags, -1, 0);
-  if (ptr == MAP_FAILED) {
-    return nullptr;
-  }
-
-  size_t aligned_size = map_size;
-  void* aligned_ptr = ptr;
-
-  std::align(align, size, aligned_ptr, aligned_size);
-
-  // Trim beginning
-  if (aligned_ptr != ptr) {
-    ptrdiff_t extra = reinterpret_cast<uintptr_t>(aligned_ptr) - reinterpret_cast<uintptr_t>(ptr);
-    munmap(ptr, extra);
-    map_size -= extra;
-    ptr = aligned_ptr;
-  }
-
-  // Trim end
-  if (map_size != size) {
-    assert(map_size > size);
-    assert(ptr != NULL);
-    munmap(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) + size), map_size - size);
-  }
-
-#if defined(PR_SET_VMA)
-  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, reinterpret_cast<uintptr_t>(ptr), size,
-        "leak_detector_malloc");
-#endif
-
-  return ptr;
-}
-
-class Chunk {
- public:
-  static void* operator new(std::size_t count) noexcept;
-  static void operator delete(void* ptr);
-  Chunk(HeapImpl* heap, int bucket);
-  ~Chunk() {}
-
-  void* Alloc();
-  void Free(void* ptr);
-  void Purge();
-  bool Empty();
-
-  static Chunk* ptr_to_chunk(void* ptr) {
-    return reinterpret_cast<Chunk*>(reinterpret_cast<uintptr_t>(ptr) & ~(kChunkSize - 1));
-  }
-  static bool is_chunk(void* ptr) {
-    return (reinterpret_cast<uintptr_t>(ptr) & (kChunkSize - 1)) != 0;
-  }
-
-  unsigned int free_count() { return free_count_; }
-  HeapImpl* heap() { return heap_; }
-  LinkedList<Chunk*> node_;  // linked list sorted by minimum free count
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Chunk);
-  HeapImpl* heap_;
-  unsigned int bucket_;
-  unsigned int allocation_size_;    // size of allocations in chunk, min 8 bytes
-  unsigned int max_allocations_;    // maximum number of allocations in the chunk
-  unsigned int first_free_bitmap_;  // index into bitmap for first non-full entry
-  unsigned int free_count_;         // number of available allocations
-  unsigned int frees_since_purge_;  // number of calls to Free since last Purge
-
-  // bitmap of pages that have been dirtied
-  uint32_t dirty_pages_[div_round_up(kUsablePagesPerChunk, 32)];
-
-  // bitmap of free allocations.
-  uint32_t free_bitmap_[kUsableChunkSize / kMinBucketAllocationSize / 32];
-
-  char data_[0];
-
-  unsigned int ptr_to_n(void* ptr) {
-    ptrdiff_t offset = reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(data_);
-    return offset / allocation_size_;
-  }
-  void* n_to_ptr(unsigned int n) { return data_ + n * allocation_size_; }
-};
-static_assert(sizeof(Chunk) <= kPageSize, "header must fit in page");
-
-// Override new operator on chunk to use mmap to allocate kChunkSize
-void* Chunk::operator new(std::size_t count __attribute__((unused))) noexcept {
-  assert(count == sizeof(Chunk));
-  void* mem = MapAligned(kChunkSize, kChunkSize);
-  if (!mem) {
-    abort();  // throw std::bad_alloc;
-  }
-
-  return mem;
-}
-
-// Override new operator on chunk to use mmap to allocate kChunkSize
-void Chunk::operator delete(void* ptr) {
-  assert(reinterpret_cast<Chunk*>(ptr) == ptr_to_chunk(ptr));
-  munmap(ptr, kChunkSize);
-}
-
-Chunk::Chunk(HeapImpl* heap, int bucket)
-    : node_(this),
-      heap_(heap),
-      bucket_(bucket),
-      allocation_size_(bucket_to_size(bucket)),
-      max_allocations_(kUsableChunkSize / allocation_size_),
-      first_free_bitmap_(0),
-      free_count_(max_allocations_),
-      frees_since_purge_(0) {
-  memset(dirty_pages_, 0, sizeof(dirty_pages_));
-  memset(free_bitmap_, 0xff, sizeof(free_bitmap_));
-}
-
-bool Chunk::Empty() {
-  return free_count_ == max_allocations_;
-}
-
-void* Chunk::Alloc() {
-  assert(free_count_ > 0);
-
-  unsigned int i = first_free_bitmap_;
-  while (free_bitmap_[i] == 0) i++;
-  assert(i < arraysize(free_bitmap_));
-  unsigned int bit = __builtin_ffs(free_bitmap_[i]) - 1;
-  assert(free_bitmap_[i] & (1U << bit));
-  free_bitmap_[i] &= ~(1U << bit);
-  unsigned int n = i * 32 + bit;
-  assert(n < max_allocations_);
-
-  unsigned int page = n * allocation_size_ / kPageSize;
-  assert(page / 32 < arraysize(dirty_pages_));
-  dirty_pages_[page / 32] |= 1U << (page % 32);
-
-  free_count_--;
-  if (free_count_ == 0) {
-    heap_->MoveToFullList(this, bucket_);
-  }
-
-  return n_to_ptr(n);
-}
-
-void Chunk::Free(void* ptr) {
-  assert(is_chunk(ptr));
-  assert(ptr_to_chunk(ptr) == this);
-
-  unsigned int n = ptr_to_n(ptr);
-  unsigned int i = n / 32;
-  unsigned int bit = n % 32;
-
-  assert(i < arraysize(free_bitmap_));
-  assert(!(free_bitmap_[i] & (1U << bit)));
-  free_bitmap_[i] |= 1U << bit;
-  free_count_++;
-
-  if (i < first_free_bitmap_) {
-    first_free_bitmap_ = i;
-  }
-
-  if (free_count_ == 1) {
-    heap_->MoveToFreeList(this, bucket_);
-  } else {
-    // TODO(ccross): move down free list if necessary
-  }
-
-  if (frees_since_purge_++ * allocation_size_ > 16 * kPageSize) {
-    Purge();
-  }
-}
-
-void Chunk::Purge() {
-  frees_since_purge_ = 0;
-
-  // unsigned int allocsPerPage = kPageSize / allocation_size_;
-}
-
-// Override new operator on HeapImpl to use mmap to allocate a page
-void* HeapImpl::operator new(std::size_t count __attribute__((unused))) noexcept {
-  assert(count == sizeof(HeapImpl));
-  void* mem = MapAligned(kPageSize, kPageSize);
-  if (!mem) {
-    abort();  // throw std::bad_alloc;
-  }
-
-  heap_count++;
-  return mem;
-}
-
-void HeapImpl::operator delete(void* ptr) {
-  munmap(ptr, kPageSize);
-}
-
-HeapImpl::HeapImpl() : free_chunks_(), full_chunks_(), map_allocation_list_(NULL) {}
-
-bool HeapImpl::Empty() {
-  for (unsigned int i = 0; i < kNumBuckets; i++) {
-    for (LinkedList<Chunk*>* it = free_chunks_[i].next(); it->data() != NULL; it = it->next()) {
-      if (!it->data()->Empty()) {
-        return false;
-      }
-    }
-    for (LinkedList<Chunk*>* it = full_chunks_[i].next(); it->data() != NULL; it = it->next()) {
-      if (!it->data()->Empty()) {
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-HeapImpl::~HeapImpl() {
-  for (unsigned int i = 0; i < kNumBuckets; i++) {
-    while (!free_chunks_[i].empty()) {
-      Chunk* chunk = free_chunks_[i].next()->data();
-      chunk->node_.remove();
-      delete chunk;
-    }
-    while (!full_chunks_[i].empty()) {
-      Chunk* chunk = full_chunks_[i].next()->data();
-      chunk->node_.remove();
-      delete chunk;
-    }
-  }
-}
-
-void* HeapImpl::Alloc(size_t size) {
-  std::lock_guard<std::mutex> lk(m_);
-  return AllocLocked(size);
-}
-
-void* HeapImpl::AllocLocked(size_t size) {
-  if (size > kMaxBucketAllocationSize) {
-    return MapAlloc(size);
-  }
-  int bucket = size_to_bucket(size);
-  if (free_chunks_[bucket].empty()) {
-    Chunk* chunk = new Chunk(this, bucket);
-    free_chunks_[bucket].insert(chunk->node_);
-  }
-  return free_chunks_[bucket].next()->data()->Alloc();
-}
-
-void HeapImpl::Free(void* ptr) {
-  std::lock_guard<std::mutex> lk(m_);
-  FreeLocked(ptr);
-}
-
-void HeapImpl::FreeLocked(void* ptr) {
-  if (!Chunk::is_chunk(ptr)) {
-    HeapImpl::MapFree(ptr);
-  } else {
-    Chunk* chunk = Chunk::ptr_to_chunk(ptr);
-    assert(chunk->heap() == this);
-    chunk->Free(ptr);
-  }
-}
-
-void* HeapImpl::MapAlloc(size_t size) {
-  size = (size + kPageSize - 1) & ~(kPageSize - 1);
-
-  MapAllocation* allocation = reinterpret_cast<MapAllocation*>(AllocLocked(sizeof(MapAllocation)));
-  void* ptr = MapAligned(size, kChunkSize);
-  if (!ptr) {
-    FreeLocked(allocation);
-    abort();  // throw std::bad_alloc;
-  }
-  allocation->ptr = ptr;
-  allocation->size = size;
-  allocation->next = map_allocation_list_;
-  map_allocation_list_ = allocation;
-
-  return ptr;
-}
-
-void HeapImpl::MapFree(void* ptr) {
-  MapAllocation** allocation = &map_allocation_list_;
-  while (*allocation && (*allocation)->ptr != ptr) allocation = &(*allocation)->next;
-
-  assert(*allocation != nullptr);
-
-  munmap((*allocation)->ptr, (*allocation)->size);
-  FreeLocked(*allocation);
-
-  *allocation = (*allocation)->next;
-}
-
-void HeapImpl::MoveToFreeList(Chunk* chunk, int bucket) {
-  MoveToList(chunk, &free_chunks_[bucket]);
-}
-
-void HeapImpl::MoveToFullList(Chunk* chunk, int bucket) {
-  MoveToList(chunk, &full_chunks_[bucket]);
-}
-
-void HeapImpl::MoveToList(Chunk* chunk, LinkedList<Chunk*>* head) {
-  // Remove from old list
-  chunk->node_.remove();
-
-  LinkedList<Chunk*>* node = head;
-  // Insert into new list, sorted by lowest free count
-  while (node->next() != head && node->data() != nullptr &&
-         node->data()->free_count() < chunk->free_count())
-    node = node->next();
-
-  node->insert(chunk->node_);
-}
-
-Heap::Heap() {
-  // HeapImpl overloads the operator new in order to mmap itself instead of
-  // allocating with new.
-  // Can't use a shared_ptr to store the result because shared_ptr needs to
-  // allocate, and Allocator<T> is still being constructed.
-  impl_ = new HeapImpl();
-  owns_impl_ = true;
-}
-
-Heap::~Heap() {
-  if (owns_impl_) {
-    delete impl_;
-  }
-}
-
-void* Heap::allocate(size_t size) {
-  return impl_->Alloc(size);
-}
-
-void Heap::deallocate(void* ptr) {
-  impl_->Free(ptr);
-}
-
-void Heap::deallocate(HeapImpl* impl, void* ptr) {
-  impl->Free(ptr);
-}
-
-bool Heap::empty() {
-  return impl_->Empty();
-}
-
-}  // namespace android
diff --git a/libmemunreachable/Allocator.h b/libmemunreachable/Allocator.h
deleted file mode 100644
index 837a12b..0000000
--- a/libmemunreachable/Allocator.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_ALLOCATOR_H_
-#define LIBMEMUNREACHABLE_ALLOCATOR_H_
-
-#include <atomic>
-#include <cstddef>
-#include <functional>
-#include <list>
-#include <map>
-#include <memory>
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-namespace android {
-
-extern std::atomic<int> heap_count;
-
-class HeapImpl;
-
-template <typename T>
-class Allocator;
-
-// Non-templated class that implements wraps HeapImpl to keep
-// implementation out of the header file
-class Heap {
- public:
-  Heap();
-  ~Heap();
-
-  // Copy constructor that does not take ownership of impl_
-  Heap(const Heap& other) : impl_(other.impl_), owns_impl_(false) {}
-
-  // Assignment disabled
-  Heap& operator=(const Heap&) = delete;
-
-  // Allocate size bytes
-  void* allocate(size_t size);
-
-  // Deallocate allocation returned by allocate
-  void deallocate(void*);
-
-  bool empty();
-
-  static void deallocate(HeapImpl* impl, void* ptr);
-
-  // Allocate a class of type T
-  template <class T>
-  T* allocate() {
-    return reinterpret_cast<T*>(allocate(sizeof(T)));
-  }
-
-  // Comparators, copied objects will be equal
-  bool operator==(const Heap& other) const { return impl_ == other.impl_; }
-  bool operator!=(const Heap& other) const { return !(*this == other); }
-
-  // std::unique_ptr wrapper that allocates using allocate and deletes using
-  // deallocate
-  template <class T>
-  using unique_ptr = std::unique_ptr<T, std::function<void(void*)>>;
-
-  template <class T, class... Args>
-  unique_ptr<T> make_unique(Args&&... args) {
-    HeapImpl* impl = impl_;
-    return unique_ptr<T>(new (allocate<T>()) T(std::forward<Args>(args)...), [impl](void* ptr) {
-      reinterpret_cast<T*>(ptr)->~T();
-      deallocate(impl, ptr);
-    });
-  }
-
-  // std::unique_ptr wrapper that allocates using allocate and deletes using
-  // deallocate
-  template <class T>
-  using shared_ptr = std::shared_ptr<T>;
-
-  template <class T, class... Args>
-  shared_ptr<T> make_shared(Args&&... args);
-
- protected:
-  HeapImpl* impl_;
-  bool owns_impl_;
-};
-
-// STLAllocator implements the std allocator interface on top of a Heap
-template <typename T>
-class STLAllocator {
- public:
-  using value_type = T;
-  ~STLAllocator() {}
-
-  // Construct an STLAllocator on top of a Heap
-  STLAllocator(const Heap& heap)
-      :  // NOLINT, implicit
-        heap_(heap) {}
-
-  // Rebind an STLAllocator from an another STLAllocator
-  template <typename U>
-  STLAllocator(const STLAllocator<U>& other)
-      :  // NOLINT, implicit
-        heap_(other.heap_) {}
-
-  STLAllocator(const STLAllocator&) = default;
-  STLAllocator<T>& operator=(const STLAllocator<T>&) = default;
-
-  T* allocate(std::size_t n) { return reinterpret_cast<T*>(heap_.allocate(n * sizeof(T))); }
-
-  void deallocate(T* ptr, std::size_t) { heap_.deallocate(ptr); }
-
-  template <typename U>
-  bool operator==(const STLAllocator<U>& other) const {
-    return heap_ == other.heap_;
-  }
-  template <typename U>
-  inline bool operator!=(const STLAllocator<U>& other) const {
-    return !(this == other);
-  }
-
-  template <typename U>
-  friend class STLAllocator;
-
- protected:
-  Heap heap_;
-};
-
-// Allocator extends STLAllocator with some convenience methods for allocating
-// a single object and for constructing unique_ptr and shared_ptr objects with
-// appropriate deleters.
-template <class T>
-class Allocator : public STLAllocator<T> {
- public:
-  ~Allocator() {}
-
-  Allocator(const Heap& other)
-      :  // NOLINT, implicit
-        STLAllocator<T>(other) {}
-
-  template <typename U>
-  Allocator(const STLAllocator<U>& other)
-      :  // NOLINT, implicit
-        STLAllocator<T>(other) {}
-
-  Allocator(const Allocator&) = default;
-  Allocator<T>& operator=(const Allocator<T>&) = default;
-
-  using STLAllocator<T>::allocate;
-  using STLAllocator<T>::deallocate;
-  using STLAllocator<T>::heap_;
-
-  T* allocate() { return STLAllocator<T>::allocate(1); }
-  void deallocate(void* ptr) { heap_.deallocate(ptr); }
-
-  using shared_ptr = Heap::shared_ptr<T>;
-
-  template <class... Args>
-  shared_ptr make_shared(Args&&... args) {
-    return heap_.template make_shared<T>(std::forward<Args>(args)...);
-  }
-
-  using unique_ptr = Heap::unique_ptr<T>;
-
-  template <class... Args>
-  unique_ptr make_unique(Args&&... args) {
-    return heap_.template make_unique<T>(std::forward<Args>(args)...);
-  }
-};
-
-// std::unique_ptr wrapper that allocates using allocate and deletes using
-// deallocate.  Implemented outside class definition in order to pass
-// Allocator<T> to shared_ptr.
-template <class T, class... Args>
-inline Heap::shared_ptr<T> Heap::make_shared(Args&&... args) {
-  return std::allocate_shared<T, Allocator<T>, Args...>(Allocator<T>(*this),
-                                                        std::forward<Args>(args)...);
-}
-
-namespace allocator {
-
-template <class T>
-using vector = std::vector<T, Allocator<T>>;
-
-template <class T>
-using list = std::list<T, Allocator<T>>;
-
-template <class Key, class T, class Compare = std::less<Key>>
-using map = std::map<Key, T, Compare, Allocator<std::pair<const Key, T>>>;
-
-template <class Key, class T, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
-using unordered_map =
-    std::unordered_map<Key, T, Hash, KeyEqual, Allocator<std::pair<const Key, T>>>;
-
-template <class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
-using unordered_set = std::unordered_set<Key, Hash, KeyEqual, Allocator<Key>>;
-
-template <class Key, class Compare = std::less<Key>>
-using set = std::set<Key, Compare, Allocator<Key>>;
-
-using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
-}
-
-}  // namespace android
-
-#endif
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
deleted file mode 100644
index 8f01e50..0000000
--- a/libmemunreachable/Android.bp
+++ /dev/null
@@ -1,103 +0,0 @@
-cc_defaults {
-    name: "libmemunreachable_defaults",
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-    shared_libs: [
-        "libbase",
-    ],
-
-    target: {
-        android: {
-            static_libs: ["libasync_safe"],
-        },
-        host: {
-            shared_libs: ["liblog"],
-        },
-    },
-}
-
-cc_library {
-    name: "libmemunreachable",
-    defaults: ["libmemunreachable_defaults"],
-    srcs: [
-        "Allocator.cpp",
-        "Binder.cpp",
-        "HeapWalker.cpp",
-        "LeakFolding.cpp",
-        "LeakPipe.cpp",
-        "MemUnreachable.cpp",
-        "ProcessMappings.cpp",
-        "PtracerThread.cpp",
-        "ThreadCapture.cpp",
-    ],
-
-    static_libs: [
-        "libc_malloc_debug_backtrace",
-        "libprocinfo",
-    ],
-    // Only need this for arm since libc++ uses its own unwind code that
-    // doesn't mix with the other default unwind code.
-    arch: {
-        arm: {
-            static_libs: ["libunwind_llvm"],
-        },
-    },
-    export_include_dirs: ["include"],
-    local_include_dirs: ["include"],
-}
-
-cc_test {
-    name: "memunreachable_test",
-    defaults: ["libmemunreachable_defaults"],
-    host_supported: true,
-    srcs: [
-        "tests/Allocator_test.cpp",
-        "tests/HeapWalker_test.cpp",
-        "tests/LeakFolding_test.cpp",
-    ],
-
-    target: {
-        android: {
-            srcs: [
-                "tests/DisableMalloc_test.cpp",
-                "tests/MemUnreachable_test.cpp",
-                "tests/ThreadCapture_test.cpp",
-            ],
-            shared_libs: [
-                "libmemunreachable",
-            ],
-        },
-        host: {
-            srcs: [
-                "Allocator.cpp",
-                "HeapWalker.cpp",
-                "LeakFolding.cpp",
-                "tests/HostMallocStub.cpp",
-            ],
-        },
-        darwin: {
-            enabled: false,
-        },
-    },
-
-    test_suites: ["device-tests"],
-}
-
-cc_test {
-    name: "memunreachable_binder_test",
-    defaults: ["libmemunreachable_defaults"],
-    srcs: [
-        "tests/Binder_test.cpp",
-    ],
-    static_libs: ["libmemunreachable"],
-    shared_libs: [
-        "libbinder",
-        "libhidlbase",
-        "libutils",
-    ],
-    test_suites: ["device-tests"],
-}
diff --git a/libmemunreachable/Binder.cpp b/libmemunreachable/Binder.cpp
deleted file mode 100644
index 60512a3..0000000
--- a/libmemunreachable/Binder.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 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 <sys/cdefs.h>
-#include <unistd.h>
-
-#include <functional>
-
-#include "Binder.h"
-#include "log.h"
-
-__BEGIN_DECLS
-
-// Weak undefined references to the symbols in libbinder and libhwbinder
-// so that libmemunreachable can call them in processes that have them
-// loaded without requiring libmemunreachable to have dependencies on them.
-ssize_t __attribute__((weak)) getBinderKernelReferences(size_t, uintptr_t*);
-ssize_t __attribute__((weak)) getHWBinderKernelReferences(size_t, uintptr_t*);
-
-__END_DECLS
-
-namespace android {
-
-static bool BinderReferencesToVector(allocator::vector<uintptr_t>& refs,
-                                     std::function<ssize_t(size_t, uintptr_t*)> fn) {
-  if (fn == nullptr) {
-    return true;
-  }
-
-  size_t size = refs.size();
-
-  do {
-    refs.resize(size);
-
-    ssize_t ret = fn(refs.size(), refs.data());
-    if (ret < 0) {
-      return false;
-    }
-
-    size = ret;
-  } while (size > refs.size());
-
-  refs.resize(size);
-  return true;
-}
-
-bool BinderReferences(allocator::vector<uintptr_t>& refs) {
-  refs.clear();
-
-  allocator::vector<uintptr_t> binder_refs{refs.get_allocator()};
-  if (BinderReferencesToVector(refs, getBinderKernelReferences)) {
-    refs.insert(refs.end(), binder_refs.begin(), binder_refs.end());
-  } else {
-    MEM_ALOGE("getBinderKernelReferences failed");
-  }
-
-  allocator::vector<uintptr_t> hwbinder_refs{refs.get_allocator()};
-  if (BinderReferencesToVector(hwbinder_refs, getHWBinderKernelReferences)) {
-    refs.insert(refs.end(), hwbinder_refs.begin(), hwbinder_refs.end());
-  } else {
-    MEM_ALOGE("getHWBinderKernelReferences failed");
-  }
-
-  return true;
-}
-
-}  // namespace android
diff --git a/libmemunreachable/Binder.h b/libmemunreachable/Binder.h
deleted file mode 100644
index bf4fd3e..0000000
--- a/libmemunreachable/Binder.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 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 LIBMEMUNREACHABLE_BINDER_H_
-#define LIBMEMUNREACHABLE_BINDER_H_
-
-#include "Allocator.h"
-
-namespace android {
-
-bool BinderReferences(allocator::vector<uintptr_t>& refs);
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_BINDER_H_
diff --git a/libmemunreachable/HeapWalker.cpp b/libmemunreachable/HeapWalker.cpp
deleted file mode 100644
index 7cae048..0000000
--- a/libmemunreachable/HeapWalker.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <map>
-#include <utility>
-
-#include "Allocator.h"
-#include "HeapWalker.h"
-#include "LeakFolding.h"
-#include "ScopedSignalHandler.h"
-#include "log.h"
-
-namespace android {
-
-bool HeapWalker::Allocation(uintptr_t begin, uintptr_t end) {
-  if (end == begin) {
-    end = begin + 1;
-  }
-  Range range{begin, end};
-  if (valid_mappings_range_.end != 0 &&
-      (begin < valid_mappings_range_.begin || end > valid_mappings_range_.end)) {
-    MEM_LOG_ALWAYS_FATAL("allocation %p-%p is outside mapping range %p-%p",
-                         reinterpret_cast<void*>(begin), reinterpret_cast<void*>(end),
-                         reinterpret_cast<void*>(valid_mappings_range_.begin),
-                         reinterpret_cast<void*>(valid_mappings_range_.end));
-  }
-  auto inserted = allocations_.insert(std::pair<Range, AllocationInfo>(range, AllocationInfo{}));
-  if (inserted.second) {
-    valid_allocations_range_.begin = std::min(valid_allocations_range_.begin, begin);
-    valid_allocations_range_.end = std::max(valid_allocations_range_.end, end);
-    allocation_bytes_ += range.size();
-    return true;
-  } else {
-    Range overlap = inserted.first->first;
-    if (overlap != range) {
-      MEM_ALOGE("range %p-%p overlaps with existing range %p-%p", reinterpret_cast<void*>(begin),
-                reinterpret_cast<void*>(end), reinterpret_cast<void*>(overlap.begin),
-                reinterpret_cast<void*>(overlap.end));
-    }
-    return false;
-  }
-}
-
-// Sanitizers may consider certain memory inaccessible through certain pointers.
-// With MTE this will need to use unchecked instructions or disable tag checking globally.
-static uintptr_t ReadWordAtAddressUnsafe(uintptr_t word_ptr)
-    __attribute__((no_sanitize("address", "hwaddress"))) {
-  return *reinterpret_cast<uintptr_t*>(word_ptr);
-}
-
-bool HeapWalker::WordContainsAllocationPtr(uintptr_t word_ptr, Range* range, AllocationInfo** info) {
-  walking_ptr_ = word_ptr;
-  // This access may segfault if the process under test has done something strange,
-  // for example mprotect(PROT_NONE) on a native heap page.  If so, it will be
-  // caught and handled by mmaping a zero page over the faulting page.
-  uintptr_t value = ReadWordAtAddressUnsafe(word_ptr);
-  walking_ptr_ = 0;
-  if (value >= valid_allocations_range_.begin && value < valid_allocations_range_.end) {
-    AllocationMap::iterator it = allocations_.find(Range{value, value + 1});
-    if (it != allocations_.end()) {
-      *range = it->first;
-      *info = &it->second;
-      return true;
-    }
-  }
-  return false;
-}
-
-void HeapWalker::RecurseRoot(const Range& root) {
-  allocator::vector<Range> to_do(1, root, allocator_);
-  while (!to_do.empty()) {
-    Range range = to_do.back();
-    to_do.pop_back();
-
-    walking_range_ = range;
-    ForEachPtrInRange(range, [&](Range& ref_range, AllocationInfo* ref_info) {
-      if (!ref_info->referenced_from_root) {
-        ref_info->referenced_from_root = true;
-        to_do.push_back(ref_range);
-      }
-    });
-    walking_range_ = Range{0, 0};
-  }
-}
-
-void HeapWalker::Mapping(uintptr_t begin, uintptr_t end) {
-  valid_mappings_range_.begin = std::min(valid_mappings_range_.begin, begin);
-  valid_mappings_range_.end = std::max(valid_mappings_range_.end, end);
-}
-
-void HeapWalker::Root(uintptr_t begin, uintptr_t end) {
-  roots_.push_back(Range{begin, end});
-}
-
-void HeapWalker::Root(const allocator::vector<uintptr_t>& vals) {
-  root_vals_.insert(root_vals_.end(), vals.begin(), vals.end());
-}
-
-size_t HeapWalker::Allocations() {
-  return allocations_.size();
-}
-
-size_t HeapWalker::AllocationBytes() {
-  return allocation_bytes_;
-}
-
-bool HeapWalker::DetectLeaks() {
-  // Recursively walk pointers from roots to mark referenced allocations
-  for (auto it = roots_.begin(); it != roots_.end(); it++) {
-    RecurseRoot(*it);
-  }
-
-  Range vals;
-  vals.begin = reinterpret_cast<uintptr_t>(root_vals_.data());
-  vals.end = vals.begin + root_vals_.size() * sizeof(uintptr_t);
-
-  RecurseRoot(vals);
-
-  if (segv_page_count_ > 0) {
-    MEM_ALOGE("%zu pages skipped due to segfaults", segv_page_count_);
-  }
-
-  return true;
-}
-
-bool HeapWalker::Leaked(allocator::vector<Range>& leaked, size_t limit, size_t* num_leaks_out,
-                        size_t* leak_bytes_out) {
-  leaked.clear();
-
-  size_t num_leaks = 0;
-  size_t leak_bytes = 0;
-  for (auto it = allocations_.begin(); it != allocations_.end(); it++) {
-    if (!it->second.referenced_from_root) {
-      num_leaks++;
-      leak_bytes += it->first.end - it->first.begin;
-    }
-  }
-
-  size_t n = 0;
-  for (auto it = allocations_.begin(); it != allocations_.end(); it++) {
-    if (!it->second.referenced_from_root) {
-      if (n++ < limit) {
-        leaked.push_back(it->first);
-      }
-    }
-  }
-
-  if (num_leaks_out) {
-    *num_leaks_out = num_leaks;
-  }
-  if (leak_bytes_out) {
-    *leak_bytes_out = leak_bytes;
-  }
-
-  return true;
-}
-
-static bool MapOverPage(void* addr) {
-  const size_t page_size = sysconf(_SC_PAGE_SIZE);
-  void* page = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & ~(page_size - 1));
-
-  void* ret = mmap(page, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
-  if (ret == MAP_FAILED) {
-    MEM_ALOGE("failed to map page at %p: %s", page, strerror(errno));
-    return false;
-  }
-
-  return true;
-}
-
-void HeapWalker::HandleSegFault(ScopedSignalHandler& handler, int signal, siginfo_t* si,
-                                void* /*uctx*/) {
-  uintptr_t addr = reinterpret_cast<uintptr_t>(si->si_addr);
-  if (addr != walking_ptr_) {
-    handler.reset();
-    return;
-  }
-  if (!segv_logged_) {
-    MEM_ALOGW("failed to read page at %p, signal %d", si->si_addr, signal);
-    if (walking_range_.begin != 0U) {
-      MEM_ALOGW("while walking range %p-%p", reinterpret_cast<void*>(walking_range_.begin),
-                reinterpret_cast<void*>(walking_range_.end));
-    }
-    segv_logged_ = true;
-  }
-  segv_page_count_++;
-  if (!MapOverPage(si->si_addr)) {
-    handler.reset();
-  }
-}
-
-Allocator<ScopedSignalHandler::SignalFnMap>::unique_ptr ScopedSignalHandler::handler_map_;
-
-}  // namespace android
diff --git a/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h
deleted file mode 100644
index f00bcca..0000000
--- a/libmemunreachable/HeapWalker.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_HEAP_WALKER_H_
-#define LIBMEMUNREACHABLE_HEAP_WALKER_H_
-
-#include <signal.h>
-
-#include "android-base/macros.h"
-
-#include "Allocator.h"
-#include "ScopedSignalHandler.h"
-#include "Tarjan.h"
-
-namespace android {
-
-// A range [begin, end)
-struct Range {
-  uintptr_t begin;
-  uintptr_t end;
-
-  size_t size() const { return end - begin; };
-  bool operator==(const Range& other) const {
-    return this->begin == other.begin && this->end == other.end;
-  }
-  bool operator!=(const Range& other) const { return !(*this == other); }
-};
-
-// Comparator for Ranges that returns equivalence for overlapping ranges
-struct compare_range {
-  bool operator()(const Range& a, const Range& b) const { return a.end <= b.begin; }
-};
-
-class HeapWalker {
- public:
-  explicit HeapWalker(Allocator<HeapWalker> allocator)
-      : allocator_(allocator),
-        allocations_(allocator),
-        allocation_bytes_(0),
-        roots_(allocator),
-        root_vals_(allocator),
-        sigsegv_handler_(allocator),
-        sigbus_handler_(allocator),
-        walking_ptr_(0),
-        walking_range_{0, 0},
-        segv_logged_(false),
-        segv_page_count_(0) {
-    valid_allocations_range_.end = 0;
-    valid_allocations_range_.begin = ~valid_allocations_range_.end;
-    valid_mappings_range_.end = 0;
-    valid_mappings_range_.begin = ~valid_allocations_range_.end;
-
-    sigsegv_handler_.install(
-        SIGSEGV, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
-          this->HandleSegFault(handler, signal, siginfo, uctx);
-        });
-    sigbus_handler_.install(
-        SIGBUS, [=](ScopedSignalHandler& handler, int signal, siginfo_t* siginfo, void* uctx) {
-          this->HandleSegFault(handler, signal, siginfo, uctx);
-        });
-  }
-
-  ~HeapWalker() {}
-  bool Allocation(uintptr_t begin, uintptr_t end);
-  void Mapping(uintptr_t begin, uintptr_t end);
-  void Root(uintptr_t begin, uintptr_t end);
-  void Root(const allocator::vector<uintptr_t>& vals);
-
-  bool DetectLeaks();
-
-  bool Leaked(allocator::vector<Range>&, size_t limit, size_t* num_leaks, size_t* leak_bytes);
-  size_t Allocations();
-  size_t AllocationBytes();
-
-  template <class F>
-  void ForEachPtrInRange(const Range& range, F&& f);
-
-  template <class F>
-  void ForEachAllocation(F&& f);
-
-  struct AllocationInfo {
-    bool referenced_from_root;
-  };
-
- private:
-  void RecurseRoot(const Range& root);
-  bool WordContainsAllocationPtr(uintptr_t ptr, Range* range, AllocationInfo** info);
-  void HandleSegFault(ScopedSignalHandler&, int, siginfo_t*, void*);
-
-  DISALLOW_COPY_AND_ASSIGN(HeapWalker);
-  Allocator<HeapWalker> allocator_;
-  using AllocationMap = allocator::map<Range, AllocationInfo, compare_range>;
-  AllocationMap allocations_;
-  size_t allocation_bytes_;
-  Range valid_allocations_range_;
-  Range valid_mappings_range_;
-
-  allocator::vector<Range> roots_;
-  allocator::vector<uintptr_t> root_vals_;
-
-  ScopedSignalHandler sigsegv_handler_;
-  ScopedSignalHandler sigbus_handler_;
-  volatile uintptr_t walking_ptr_;
-  Range walking_range_;
-  bool segv_logged_;
-  size_t segv_page_count_;
-};
-
-template <class F>
-inline void HeapWalker::ForEachPtrInRange(const Range& range, F&& f) {
-  uintptr_t begin = (range.begin + (sizeof(uintptr_t) - 1)) & ~(sizeof(uintptr_t) - 1);
-  // TODO(ccross): we might need to consider a pointer to the end of a buffer
-  // to be inside the buffer, which means the common case of a pointer to the
-  // beginning of a buffer may keep two ranges live.
-  for (uintptr_t i = begin; i < range.end; i += sizeof(uintptr_t)) {
-    Range ref_range;
-    AllocationInfo* ref_info;
-    if (WordContainsAllocationPtr(i, &ref_range, &ref_info)) {
-      f(ref_range, ref_info);
-    }
-  }
-}
-
-template <class F>
-inline void HeapWalker::ForEachAllocation(F&& f) {
-  for (auto& it : allocations_) {
-    const Range& range = it.first;
-    HeapWalker::AllocationInfo& allocation = it.second;
-    f(range, allocation);
-  }
-}
-
-}  // namespace android
-
-#endif
diff --git a/libmemunreachable/Leak.h b/libmemunreachable/Leak.h
deleted file mode 100644
index de64b64..0000000
--- a/libmemunreachable/Leak.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_LEAK_H_
-#define LIBMEMUNREACHABLE_LEAK_H_
-
-#include <functional>
-#include <vector>
-
-#include "memunreachable/memunreachable.h"
-
-// Custom std::hash specialization so that Leak::Backtrace can be used
-// as a key in std::unordered_map.
-namespace std {
-
-template <>
-struct hash<android::Leak::Backtrace> {
-  std::size_t operator()(const android::Leak::Backtrace& key) const {
-    std::size_t seed = 0;
-
-    hash_combine(seed, key.num_frames);
-    for (size_t i = 0; i < key.num_frames; i++) {
-      hash_combine(seed, key.frames[i]);
-    }
-
-    return seed;
-  }
-
- private:
-  template <typename T>
-  inline void hash_combine(std::size_t& seed, const T& v) const {
-    std::hash<T> hasher;
-    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
-  }
-};
-
-}  // namespace std
-
-namespace android {
-
-static bool operator==(const Leak::Backtrace& lhs, const Leak::Backtrace& rhs) {
-  return (lhs.num_frames == rhs.num_frames) &&
-         memcmp(lhs.frames, rhs.frames, lhs.num_frames * sizeof(lhs.frames[0])) == 0;
-}
-}
-
-#endif
diff --git a/libmemunreachable/LeakFolding.cpp b/libmemunreachable/LeakFolding.cpp
deleted file mode 100644
index 074dc48..0000000
--- a/libmemunreachable/LeakFolding.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 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 <inttypes.h>
-
-#include "Allocator.h"
-#include "HeapWalker.h"
-#include "LeakFolding.h"
-#include "Tarjan.h"
-#include "log.h"
-
-namespace android {
-
-// Converts possibly cyclic graph of leaks to a DAG by combining
-// strongly-connected components into a object, stored in the scc pointer
-// of each node in the component.
-void LeakFolding::ComputeDAG() {
-  SCCList<LeakInfo> scc_list{allocator_};
-  Tarjan(leak_graph_, scc_list);
-
-  Allocator<SCCInfo> scc_allocator = allocator_;
-
-  for (auto& scc_nodes : scc_list) {
-    Allocator<SCCInfo>::unique_ptr leak_scc;
-    leak_scc = scc_allocator.make_unique(scc_allocator);
-
-    for (auto& node : scc_nodes) {
-      node->ptr->scc = leak_scc.get();
-      leak_scc->count++;
-      leak_scc->size += node->ptr->range.size();
-    }
-
-    leak_scc_.emplace_back(std::move(leak_scc));
-  }
-
-  for (auto& it : leak_map_) {
-    LeakInfo& leak = it.second;
-    for (auto& ref : leak.node.references_out) {
-      if (leak.scc != ref->ptr->scc) {
-        leak.scc->node.Edge(&ref->ptr->scc->node);
-      }
-    }
-  }
-}
-
-void LeakFolding::AccumulateLeaks(SCCInfo* dominator) {
-  std::function<void(SCCInfo*)> walk([&](SCCInfo* scc) {
-    if (scc->accumulator != dominator) {
-      scc->accumulator = dominator;
-      dominator->cuumulative_size += scc->size;
-      dominator->cuumulative_count += scc->count;
-      scc->node.Foreach([&](SCCInfo* ref) { walk(ref); });
-    }
-  });
-  walk(dominator);
-}
-
-bool LeakFolding::FoldLeaks() {
-  Allocator<LeakInfo> leak_allocator = allocator_;
-
-  // Find all leaked allocations insert them into leak_map_ and leak_graph_
-  heap_walker_.ForEachAllocation([&](const Range& range, HeapWalker::AllocationInfo& allocation) {
-    if (!allocation.referenced_from_root) {
-      auto it = leak_map_.emplace(std::piecewise_construct, std::forward_as_tuple(range),
-                                  std::forward_as_tuple(range, allocator_));
-      LeakInfo& leak = it.first->second;
-      leak_graph_.push_back(&leak.node);
-    }
-  });
-
-  // Find references between leaked allocations and connect them in leak_graph_
-  for (auto& it : leak_map_) {
-    LeakInfo& leak = it.second;
-    heap_walker_.ForEachPtrInRange(leak.range,
-                                   [&](Range& ptr_range, HeapWalker::AllocationInfo* ptr_info) {
-                                     if (!ptr_info->referenced_from_root) {
-                                       LeakInfo* ptr_leak = &leak_map_.at(ptr_range);
-                                       leak.node.Edge(&ptr_leak->node);
-                                     }
-                                   });
-  }
-
-  // Convert the cyclic graph to a DAG by grouping strongly connected components
-  ComputeDAG();
-
-  // Compute dominators and cuumulative sizes
-  for (auto& scc : leak_scc_) {
-    if (scc->node.references_in.size() == 0) {
-      scc->dominator = true;
-      AccumulateLeaks(scc.get());
-    }
-  }
-
-  return true;
-}
-
-bool LeakFolding::Leaked(allocator::vector<LeakFolding::Leak>& leaked, size_t* num_leaks_out,
-                         size_t* leak_bytes_out) {
-  size_t num_leaks = 0;
-  size_t leak_bytes = 0;
-  for (auto& it : leak_map_) {
-    const LeakInfo& leak = it.second;
-    num_leaks++;
-    leak_bytes += leak.range.size();
-  }
-
-  for (auto& it : leak_map_) {
-    const LeakInfo& leak = it.second;
-    if (leak.scc->dominator) {
-      leaked.emplace_back(Leak{leak.range, leak.scc->cuumulative_count - 1,
-                               leak.scc->cuumulative_size - leak.range.size()});
-    }
-  }
-
-  if (num_leaks_out) {
-    *num_leaks_out = num_leaks;
-  }
-  if (leak_bytes_out) {
-    *leak_bytes_out = leak_bytes;
-  }
-
-  return true;
-}
-
-}  // namespace android
diff --git a/libmemunreachable/LeakFolding.h b/libmemunreachable/LeakFolding.h
deleted file mode 100644
index 09affac..0000000
--- a/libmemunreachable/LeakFolding.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_LEAK_FOLDING_H_
-#define LIBMEMUNREACHABLE_LEAK_FOLDING_H_
-
-#include "HeapWalker.h"
-
-namespace android {
-
-class LeakFolding {
- public:
-  LeakFolding(Allocator<void> allocator, HeapWalker& heap_walker)
-      : allocator_(allocator),
-        heap_walker_(heap_walker),
-        leak_map_(allocator),
-        leak_graph_(allocator),
-        leak_scc_(allocator) {}
-
-  bool FoldLeaks();
-
-  struct Leak {
-    const Range range;
-    size_t referenced_count;
-    size_t referenced_size;
-  };
-
-  bool Leaked(allocator::vector<Leak>& leaked, size_t* num_leaks_out, size_t* leak_bytes_out);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LeakFolding);
-  Allocator<void> allocator_;
-  HeapWalker& heap_walker_;
-
-  struct SCCInfo {
-   public:
-    Node<SCCInfo> node;
-
-    size_t count;
-    size_t size;
-
-    size_t cuumulative_count;
-    size_t cuumulative_size;
-
-    bool dominator;
-    SCCInfo* accumulator;
-
-    explicit SCCInfo(Allocator<SCCInfo> allocator)
-        : node(this, allocator),
-          count(0),
-          size(0),
-          cuumulative_count(0),
-          cuumulative_size(0),
-          dominator(false),
-          accumulator(nullptr) {}
-
-   private:
-    SCCInfo(SCCInfo&&) = delete;
-    DISALLOW_COPY_AND_ASSIGN(SCCInfo);
-  };
-
-  struct LeakInfo {
-   public:
-    Node<LeakInfo> node;
-
-    const Range range;
-
-    SCCInfo* scc;
-
-    LeakInfo(const Range& range, Allocator<LeakInfo> allocator)
-        : node(this, allocator), range(range), scc(nullptr) {}
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(LeakInfo);
-  };
-
-  void ComputeDAG();
-  void AccumulateLeaks(SCCInfo* dominator);
-
-  allocator::map<Range, LeakInfo, compare_range> leak_map_;
-  Graph<LeakInfo> leak_graph_;
-  allocator::vector<Allocator<SCCInfo>::unique_ptr> leak_scc_;
-};
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_LEAK_FOLDING_H_
diff --git a/libmemunreachable/LeakPipe.cpp b/libmemunreachable/LeakPipe.cpp
deleted file mode 100644
index 8ea9ad6..0000000
--- a/libmemunreachable/LeakPipe.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <string.h>
-
-#include "LeakPipe.h"
-
-#include "log.h"
-
-namespace android {
-
-bool LeakPipe::SendFd(int sock, int fd) {
-  struct msghdr hdr {};
-  struct iovec iov {};
-  unsigned int data = 0xfdfdfdfd;
-  alignas(struct cmsghdr) char cmsgbuf[CMSG_SPACE(sizeof(int))];
-
-  hdr.msg_iov = &iov;
-  hdr.msg_iovlen = 1;
-  iov.iov_base = &data;
-  iov.iov_len = sizeof(data);
-
-  hdr.msg_control = cmsgbuf;
-  hdr.msg_controllen = CMSG_LEN(sizeof(int));
-
-  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
-  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
-  cmsg->cmsg_level = SOL_SOCKET;
-  cmsg->cmsg_type = SCM_RIGHTS;
-
-  *(int*)CMSG_DATA(cmsg) = fd;
-
-  int ret = sendmsg(sock, &hdr, 0);
-  if (ret < 0) {
-    MEM_ALOGE("failed to send fd: %s", strerror(errno));
-    return false;
-  }
-  if (ret == 0) {
-    MEM_ALOGE("eof when sending fd");
-    return false;
-  }
-
-  return true;
-}
-
-int LeakPipe::ReceiveFd(int sock) {
-  struct msghdr hdr {};
-  struct iovec iov {};
-  unsigned int data;
-  alignas(struct cmsghdr) char cmsgbuf[CMSG_SPACE(sizeof(int))];
-
-  hdr.msg_iov = &iov;
-  hdr.msg_iovlen = 1;
-  iov.iov_base = &data;
-  iov.iov_len = sizeof(data);
-
-  hdr.msg_control = cmsgbuf;
-  hdr.msg_controllen = CMSG_LEN(sizeof(int));
-
-  int ret = recvmsg(sock, &hdr, 0);
-  if (ret < 0) {
-    MEM_ALOGE("failed to receive fd: %s", strerror(errno));
-    return -1;
-  }
-  if (ret == 0) {
-    MEM_ALOGE("eof when receiving fd");
-    return -1;
-  }
-
-  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
-  if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
-    MEM_ALOGE("missing fd while receiving fd");
-    return -1;
-  }
-
-  return *(int*)CMSG_DATA(cmsg);
-}
-
-}  // namespace android
diff --git a/libmemunreachable/LeakPipe.h b/libmemunreachable/LeakPipe.h
deleted file mode 100644
index 94d4aa4..0000000
--- a/libmemunreachable/LeakPipe.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_LEAK_PIPE_H_
-#define LIBMEMUNREACHABLE_LEAK_PIPE_H_
-
-#include <sys/socket.h>
-
-#include <vector>
-
-#include "android-base/macros.h"
-
-#include "ScopedPipe.h"
-#include "log.h"
-
-namespace android {
-
-// LeakPipe implements a pipe that can transfer vectors of simple objects
-// between processes.  The pipe is created in the sending process and
-// transferred over a socketpair that was created before forking.  This ensures
-// that only the sending process can have the send side of the pipe open, so if
-// the sending process dies the pipe will close.
-class LeakPipe {
- public:
-  LeakPipe() {
-    int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv_);
-    if (ret < 0) {
-      MEM_LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno));
-    }
-  }
-
-  ~LeakPipe() { Close(); }
-
-  void Close() {
-    close(sv_[0]);
-    close(sv_[1]);
-    sv_[0] = -1;
-    sv_[1] = -1;
-  }
-
-  bool OpenReceiver() {
-    int fd = ReceiveFd(sv_[0]);
-    if (fd < 0) {
-      return false;
-    }
-
-    receiver_.SetFd(fd);
-    return true;
-  }
-
-  bool OpenSender() {
-    ScopedPipe pipe;
-
-    if (!SendFd(sv_[1], pipe.Receiver())) {
-      return false;
-    }
-    pipe.ReleaseReceiver();
-
-    sender_.SetFd(pipe.ReleaseSender());
-    return true;
-  }
-
-  class LeakPipeBase {
-   public:
-    LeakPipeBase() : fd_(-1) {}
-
-    ~LeakPipeBase() { Close(); }
-
-    void SetFd(int fd) { fd_ = fd; }
-
-    void Close() {
-      close(fd_);
-      fd_ = -1;
-    }
-
-   protected:
-    int fd_;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(LeakPipeBase);
-  };
-
-  class LeakPipeSender : public LeakPipeBase {
-   public:
-    using LeakPipeBase::LeakPipeBase;
-
-    template <typename T>
-    bool Send(const T& value) {
-      ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T)));
-      if (ret < 0) {
-        MEM_ALOGE("failed to send value: %s", strerror(errno));
-        return false;
-      } else if (static_cast<size_t>(ret) != sizeof(T)) {
-        MEM_ALOGE("eof while writing value");
-        return false;
-      }
-
-      return true;
-    }
-
-    template <class T, class Alloc = std::allocator<T>>
-    bool SendVector(const std::vector<T, Alloc>& vector) {
-      size_t size = vector.size() * sizeof(T);
-      if (!Send(size)) {
-        return false;
-      }
-
-      ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, vector.data(), size));
-      if (ret < 0) {
-        MEM_ALOGE("failed to send vector: %s", strerror(errno));
-        return false;
-      } else if (static_cast<size_t>(ret) != size) {
-        MEM_ALOGE("eof while writing vector");
-        return false;
-      }
-
-      return true;
-    }
-  };
-
-  class LeakPipeReceiver : public LeakPipeBase {
-   public:
-    using LeakPipeBase::LeakPipeBase;
-
-    template <typename T>
-    bool Receive(T* value) {
-      ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T)));
-      if (ret < 0) {
-        MEM_ALOGE("failed to receive value: %s", strerror(errno));
-        return false;
-      } else if (static_cast<size_t>(ret) != sizeof(T)) {
-        MEM_ALOGE("eof while receiving value");
-        return false;
-      }
-
-      return true;
-    }
-
-    template <class T, class Alloc = std::allocator<T>>
-    bool ReceiveVector(std::vector<T, Alloc>& vector) {
-      size_t size = 0;
-      if (!Receive(&size)) {
-        return false;
-      }
-
-      vector.resize(size / sizeof(T));
-
-      char* ptr = reinterpret_cast<char*>(vector.data());
-      while (size > 0) {
-        ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, ptr, size));
-        if (ret < 0) {
-          MEM_ALOGE("failed to send vector: %s", strerror(errno));
-          return false;
-        } else if (ret == 0) {
-          MEM_ALOGE("eof while reading vector");
-          return false;
-        }
-        size -= ret;
-        ptr += ret;
-      }
-
-      return true;
-    }
-  };
-
-  LeakPipeReceiver& Receiver() { return receiver_; }
-
-  LeakPipeSender& Sender() { return sender_; }
-
- private:
-  LeakPipeReceiver receiver_;
-  LeakPipeSender sender_;
-  bool SendFd(int sock, int fd);
-  int ReceiveFd(int sock);
-  DISALLOW_COPY_AND_ASSIGN(LeakPipe);
-  int sv_[2];
-};
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_LEAK_PIPE_H_
diff --git a/libmemunreachable/LinkedList.h b/libmemunreachable/LinkedList.h
deleted file mode 100644
index 36fe9fd..0000000
--- a/libmemunreachable/LinkedList.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_LINKED_LIST_H_
-#define LIBMEMUNREACHABLE_LINKED_LIST_H_
-
-namespace android {
-
-template <class T>
-class LinkedList {
- public:
-  LinkedList() : next_(this), prev_(this), data_() {}
-  explicit LinkedList(T data) : LinkedList() { data_ = data; }
-  ~LinkedList() {}
-  void insert(LinkedList<T>& node) {
-    assert(node.empty());
-    node.next_ = this->next_;
-    node.next_->prev_ = &node;
-    this->next_ = &node;
-    node.prev_ = this;
-  }
-  void remove() {
-    this->next_->prev_ = this->prev_;
-    this->prev_->next_ = this->next_;
-    this->next_ = this;
-    this->prev_ = this;
-  }
-  T data() { return data_; }
-  bool empty() { return next_ == this && prev_ == this; }
-  LinkedList<T>* next() { return next_; }
-
- private:
-  LinkedList<T>* next_;
-  LinkedList<T>* prev_;
-  T data_;
-};
-
-template <class T>
-class LinkedListHead {
- public:
-  LinkedListHead() : node_() {}
-  ~LinkedListHead() {}
-
- private:
-  LinkedList<T> node_;
-};
-
-}  // namespace android
-
-#endif
diff --git a/libmemunreachable/MemUnreachable.cpp b/libmemunreachable/MemUnreachable.cpp
deleted file mode 100644
index 299c320..0000000
--- a/libmemunreachable/MemUnreachable.cpp
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2016 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 <inttypes.h>
-#include <string.h>
-
-#include <functional>
-#include <iomanip>
-#include <mutex>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-
-#include <android-base/macros.h>
-#include <backtrace.h>
-
-#include "Allocator.h"
-#include "Binder.h"
-#include "HeapWalker.h"
-#include "Leak.h"
-#include "LeakFolding.h"
-#include "LeakPipe.h"
-#include "ProcessMappings.h"
-#include "PtracerThread.h"
-#include "ScopedDisableMalloc.h"
-#include "Semaphore.h"
-#include "ThreadCapture.h"
-
-#include "bionic.h"
-#include "log.h"
-#include "memunreachable/memunreachable.h"
-
-using namespace std::chrono_literals;
-
-namespace android {
-
-const size_t Leak::contents_length;
-
-class MemUnreachable {
- public:
-  MemUnreachable(pid_t pid, Allocator<void> allocator)
-      : pid_(pid), allocator_(allocator), heap_walker_(allocator_) {}
-  bool CollectAllocations(const allocator::vector<ThreadInfo>& threads,
-                          const allocator::vector<Mapping>& mappings,
-                          const allocator::vector<uintptr_t>& refs);
-  bool GetUnreachableMemory(allocator::vector<Leak>& leaks, size_t limit, size_t* num_leaks,
-                            size_t* leak_bytes);
-  size_t Allocations() { return heap_walker_.Allocations(); }
-  size_t AllocationBytes() { return heap_walker_.AllocationBytes(); }
-
- private:
-  bool ClassifyMappings(const allocator::vector<Mapping>& mappings,
-                        allocator::vector<Mapping>& heap_mappings,
-                        allocator::vector<Mapping>& anon_mappings,
-                        allocator::vector<Mapping>& globals_mappings,
-                        allocator::vector<Mapping>& stack_mappings);
-  DISALLOW_COPY_AND_ASSIGN(MemUnreachable);
-  pid_t pid_;
-  Allocator<void> allocator_;
-  HeapWalker heap_walker_;
-};
-
-static void HeapIterate(const Mapping& heap_mapping,
-                        const std::function<void(uintptr_t, size_t)>& func) {
-  malloc_iterate(heap_mapping.begin, heap_mapping.end - heap_mapping.begin,
-                 [](uintptr_t base, size_t size, void* arg) {
-                   auto f = reinterpret_cast<const std::function<void(uintptr_t, size_t)>*>(arg);
-                   (*f)(base, size);
-                 },
-                 const_cast<void*>(reinterpret_cast<const void*>(&func)));
-}
-
-bool MemUnreachable::CollectAllocations(const allocator::vector<ThreadInfo>& threads,
-                                        const allocator::vector<Mapping>& mappings,
-                                        const allocator::vector<uintptr_t>& refs) {
-  MEM_ALOGI("searching process %d for allocations", pid_);
-
-  for (auto it = mappings.begin(); it != mappings.end(); it++) {
-    heap_walker_.Mapping(it->begin, it->end);
-  }
-
-  allocator::vector<Mapping> heap_mappings{mappings};
-  allocator::vector<Mapping> anon_mappings{mappings};
-  allocator::vector<Mapping> globals_mappings{mappings};
-  allocator::vector<Mapping> stack_mappings{mappings};
-  if (!ClassifyMappings(mappings, heap_mappings, anon_mappings, globals_mappings, stack_mappings)) {
-    return false;
-  }
-
-  for (auto it = heap_mappings.begin(); it != heap_mappings.end(); it++) {
-    MEM_ALOGV("Heap mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name);
-    HeapIterate(*it,
-                [&](uintptr_t base, size_t size) { heap_walker_.Allocation(base, base + size); });
-  }
-
-  for (auto it = anon_mappings.begin(); it != anon_mappings.end(); it++) {
-    MEM_ALOGV("Anon mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name);
-    heap_walker_.Allocation(it->begin, it->end);
-  }
-
-  for (auto it = globals_mappings.begin(); it != globals_mappings.end(); it++) {
-    MEM_ALOGV("Globals mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name);
-    heap_walker_.Root(it->begin, it->end);
-  }
-
-  for (auto thread_it = threads.begin(); thread_it != threads.end(); thread_it++) {
-    for (auto it = stack_mappings.begin(); it != stack_mappings.end(); it++) {
-      if (thread_it->stack.first >= it->begin && thread_it->stack.first <= it->end) {
-        MEM_ALOGV("Stack %" PRIxPTR "-%" PRIxPTR " %s", thread_it->stack.first, it->end, it->name);
-        heap_walker_.Root(thread_it->stack.first, it->end);
-      }
-    }
-    heap_walker_.Root(thread_it->regs);
-  }
-
-  heap_walker_.Root(refs);
-
-  MEM_ALOGI("searching done");
-
-  return true;
-}
-
-bool MemUnreachable::GetUnreachableMemory(allocator::vector<Leak>& leaks, size_t limit,
-                                          size_t* num_leaks, size_t* leak_bytes) {
-  MEM_ALOGI("sweeping process %d for unreachable memory", pid_);
-  leaks.clear();
-
-  if (!heap_walker_.DetectLeaks()) {
-    return false;
-  }
-
-  allocator::vector<Range> leaked1{allocator_};
-  heap_walker_.Leaked(leaked1, 0, num_leaks, leak_bytes);
-
-  MEM_ALOGI("sweeping done");
-
-  MEM_ALOGI("folding related leaks");
-
-  LeakFolding folding(allocator_, heap_walker_);
-  if (!folding.FoldLeaks()) {
-    return false;
-  }
-
-  allocator::vector<LeakFolding::Leak> leaked{allocator_};
-
-  if (!folding.Leaked(leaked, num_leaks, leak_bytes)) {
-    return false;
-  }
-
-  allocator::unordered_map<Leak::Backtrace, Leak*> backtrace_map{allocator_};
-
-  // Prevent reallocations of backing memory so we can store pointers into it
-  // in backtrace_map.
-  leaks.reserve(leaked.size());
-
-  for (auto& it : leaked) {
-    leaks.emplace_back();
-    Leak* leak = &leaks.back();
-
-    ssize_t num_backtrace_frames = malloc_backtrace(
-        reinterpret_cast<void*>(it.range.begin), leak->backtrace.frames, leak->backtrace.max_frames);
-    if (num_backtrace_frames > 0) {
-      leak->backtrace.num_frames = num_backtrace_frames;
-
-      auto inserted = backtrace_map.emplace(leak->backtrace, leak);
-      if (!inserted.second) {
-        // Leak with same backtrace already exists, drop this one and
-        // increment similar counts on the existing one.
-        leaks.pop_back();
-        Leak* similar_leak = inserted.first->second;
-        similar_leak->similar_count++;
-        similar_leak->similar_size += it.range.size();
-        similar_leak->similar_referenced_count += it.referenced_count;
-        similar_leak->similar_referenced_size += it.referenced_size;
-        similar_leak->total_size += it.range.size();
-        similar_leak->total_size += it.referenced_size;
-        continue;
-      }
-    }
-
-    leak->begin = it.range.begin;
-    leak->size = it.range.size();
-    leak->referenced_count = it.referenced_count;
-    leak->referenced_size = it.referenced_size;
-    leak->total_size = leak->size + leak->referenced_size;
-    memcpy(leak->contents, reinterpret_cast<void*>(it.range.begin),
-           std::min(leak->size, Leak::contents_length));
-  }
-
-  MEM_ALOGI("folding done");
-
-  std::sort(leaks.begin(), leaks.end(),
-            [](const Leak& a, const Leak& b) { return a.total_size > b.total_size; });
-
-  if (leaks.size() > limit) {
-    leaks.resize(limit);
-  }
-
-  return true;
-}
-
-static bool has_prefix(const allocator::string& s, const char* prefix) {
-  int ret = s.compare(0, strlen(prefix), prefix);
-  return ret == 0;
-}
-
-static bool is_sanitizer_mapping(const allocator::string& s) {
-  return s == "[anon:low shadow]" || s == "[anon:high shadow]" || has_prefix(s, "[anon:hwasan");
-}
-
-bool MemUnreachable::ClassifyMappings(const allocator::vector<Mapping>& mappings,
-                                      allocator::vector<Mapping>& heap_mappings,
-                                      allocator::vector<Mapping>& anon_mappings,
-                                      allocator::vector<Mapping>& globals_mappings,
-                                      allocator::vector<Mapping>& stack_mappings) {
-  heap_mappings.clear();
-  anon_mappings.clear();
-  globals_mappings.clear();
-  stack_mappings.clear();
-
-  allocator::string current_lib{allocator_};
-
-  for (auto it = mappings.begin(); it != mappings.end(); it++) {
-    if (it->execute) {
-      current_lib = it->name;
-      continue;
-    }
-
-    if (!it->read) {
-      continue;
-    }
-
-    const allocator::string mapping_name{it->name, allocator_};
-    if (mapping_name == "[anon:.bss]") {
-      // named .bss section
-      globals_mappings.emplace_back(*it);
-    } else if (mapping_name == current_lib) {
-      // .rodata or .data section
-      globals_mappings.emplace_back(*it);
-    } else if (mapping_name == "[anon:libc_malloc]") {
-      // named malloc mapping
-      heap_mappings.emplace_back(*it);
-    } else if (has_prefix(mapping_name, "[anon:dalvik-")) {
-      // named dalvik heap mapping
-      globals_mappings.emplace_back(*it);
-    } else if (has_prefix(mapping_name, "[stack")) {
-      // named stack mapping
-      stack_mappings.emplace_back(*it);
-    } else if (mapping_name.size() == 0) {
-      globals_mappings.emplace_back(*it);
-    } else if (has_prefix(mapping_name, "[anon:") &&
-               mapping_name != "[anon:leak_detector_malloc]" &&
-               !is_sanitizer_mapping(mapping_name)) {
-      // TODO(ccross): it would be nice to treat named anonymous mappings as
-      // possible leaks, but naming something in a .bss or .data section makes
-      // it impossible to distinguish them from mmaped and then named mappings.
-      globals_mappings.emplace_back(*it);
-    }
-  }
-
-  return true;
-}
-
-template <typename T>
-static inline const char* plural(T val) {
-  return (val == 1) ? "" : "s";
-}
-
-bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit) {
-  int parent_pid = getpid();
-  int parent_tid = gettid();
-
-  Heap heap;
-
-  Semaphore continue_parent_sem;
-  LeakPipe pipe;
-
-  PtracerThread thread{[&]() -> int {
-    /////////////////////////////////////////////
-    // Collection thread
-    /////////////////////////////////////////////
-    MEM_ALOGI("collecting thread info for process %d...", parent_pid);
-
-    ThreadCapture thread_capture(parent_pid, heap);
-    allocator::vector<ThreadInfo> thread_info(heap);
-    allocator::vector<Mapping> mappings(heap);
-    allocator::vector<uintptr_t> refs(heap);
-
-    // ptrace all the threads
-    if (!thread_capture.CaptureThreads()) {
-      continue_parent_sem.Post();
-      return 1;
-    }
-
-    // collect register contents and stacks
-    if (!thread_capture.CapturedThreadInfo(thread_info)) {
-      continue_parent_sem.Post();
-      return 1;
-    }
-
-    // snapshot /proc/pid/maps
-    if (!ProcessMappings(parent_pid, mappings)) {
-      continue_parent_sem.Post();
-      return 1;
-    }
-
-    if (!BinderReferences(refs)) {
-      continue_parent_sem.Post();
-      return 1;
-    }
-
-    // malloc must be enabled to call fork, at_fork handlers take the same
-    // locks as ScopedDisableMalloc.  All threads are paused in ptrace, so
-    // memory state is still consistent.  Unfreeze the original thread so it
-    // can drop the malloc locks, it will block until the collection thread
-    // exits.
-    thread_capture.ReleaseThread(parent_tid);
-    continue_parent_sem.Post();
-
-    // fork a process to do the heap walking
-    int ret = fork();
-    if (ret < 0) {
-      return 1;
-    } else if (ret == 0) {
-      /////////////////////////////////////////////
-      // Heap walker process
-      /////////////////////////////////////////////
-      // Examine memory state in the child using the data collected above and
-      // the CoW snapshot of the process memory contents.
-
-      if (!pipe.OpenSender()) {
-        _exit(1);
-      }
-
-      MemUnreachable unreachable{parent_pid, heap};
-
-      if (!unreachable.CollectAllocations(thread_info, mappings, refs)) {
-        _exit(2);
-      }
-      size_t num_allocations = unreachable.Allocations();
-      size_t allocation_bytes = unreachable.AllocationBytes();
-
-      allocator::vector<Leak> leaks{heap};
-
-      size_t num_leaks = 0;
-      size_t leak_bytes = 0;
-      bool ok = unreachable.GetUnreachableMemory(leaks, limit, &num_leaks, &leak_bytes);
-
-      ok = ok && pipe.Sender().Send(num_allocations);
-      ok = ok && pipe.Sender().Send(allocation_bytes);
-      ok = ok && pipe.Sender().Send(num_leaks);
-      ok = ok && pipe.Sender().Send(leak_bytes);
-      ok = ok && pipe.Sender().SendVector(leaks);
-
-      if (!ok) {
-        _exit(3);
-      }
-
-      _exit(0);
-    } else {
-      // Nothing left to do in the collection thread, return immediately,
-      // releasing all the captured threads.
-      MEM_ALOGI("collection thread done");
-      return 0;
-    }
-  }};
-
-  /////////////////////////////////////////////
-  // Original thread
-  /////////////////////////////////////////////
-
-  {
-    // Disable malloc to get a consistent view of memory
-    ScopedDisableMalloc disable_malloc;
-
-    // Start the collection thread
-    thread.Start();
-
-    // Wait for the collection thread to signal that it is ready to fork the
-    // heap walker process.
-    continue_parent_sem.Wait(30s);
-
-    // Re-enable malloc so the collection thread can fork.
-  }
-
-  // Wait for the collection thread to exit
-  int ret = thread.Join();
-  if (ret != 0) {
-    return false;
-  }
-
-  // Get a pipe from the heap walker process.  Transferring a new pipe fd
-  // ensures no other forked processes can have it open, so when the heap
-  // walker process dies the remote side of the pipe will close.
-  if (!pipe.OpenReceiver()) {
-    return false;
-  }
-
-  bool ok = true;
-  ok = ok && pipe.Receiver().Receive(&info.num_allocations);
-  ok = ok && pipe.Receiver().Receive(&info.allocation_bytes);
-  ok = ok && pipe.Receiver().Receive(&info.num_leaks);
-  ok = ok && pipe.Receiver().Receive(&info.leak_bytes);
-  ok = ok && pipe.Receiver().ReceiveVector(info.leaks);
-  if (!ok) {
-    return false;
-  }
-
-  MEM_ALOGI("unreachable memory detection done");
-  MEM_ALOGE("%zu bytes in %zu allocation%s unreachable out of %zu bytes in %zu allocation%s",
-            info.leak_bytes, info.num_leaks, plural(info.num_leaks), info.allocation_bytes,
-            info.num_allocations, plural(info.num_allocations));
-  return true;
-}
-
-std::string Leak::ToString(bool log_contents) const {
-  std::ostringstream oss;
-
-  oss << "  " << std::dec << size;
-  oss << " bytes unreachable at ";
-  oss << std::hex << begin;
-  oss << std::endl;
-  if (referenced_count > 0) {
-    oss << std::dec;
-    oss << "   referencing " << referenced_size << " unreachable bytes";
-    oss << " in " << referenced_count << " allocation" << plural(referenced_count);
-    oss << std::endl;
-  }
-  if (similar_count > 0) {
-    oss << std::dec;
-    oss << "   and " << similar_size << " similar unreachable bytes";
-    oss << " in " << similar_count << " allocation" << plural(similar_count);
-    oss << std::endl;
-    if (similar_referenced_count > 0) {
-      oss << "   referencing " << similar_referenced_size << " unreachable bytes";
-      oss << " in " << similar_referenced_count << " allocation" << plural(similar_referenced_count);
-      oss << std::endl;
-    }
-  }
-
-  if (log_contents) {
-    const int bytes_per_line = 16;
-    const size_t bytes = std::min(size, contents_length);
-
-    if (bytes == size) {
-      oss << "   contents:" << std::endl;
-    } else {
-      oss << "   first " << bytes << " bytes of contents:" << std::endl;
-    }
-
-    for (size_t i = 0; i < bytes; i += bytes_per_line) {
-      oss << "   " << std::hex << begin + i << ": ";
-      size_t j;
-      oss << std::setfill('0');
-      for (j = i; j < bytes && j < i + bytes_per_line; j++) {
-        oss << std::setw(2) << static_cast<int>(contents[j]) << " ";
-      }
-      oss << std::setfill(' ');
-      for (; j < i + bytes_per_line; j++) {
-        oss << "   ";
-      }
-      for (j = i; j < bytes && j < i + bytes_per_line; j++) {
-        char c = contents[j];
-        if (c < ' ' || c >= 0x7f) {
-          c = '.';
-        }
-        oss << c;
-      }
-      oss << std::endl;
-    }
-  }
-  if (backtrace.num_frames > 0) {
-    oss << backtrace_string(backtrace.frames, backtrace.num_frames);
-  }
-
-  return oss.str();
-}
-
-std::string UnreachableMemoryInfo::ToString(bool log_contents) const {
-  std::ostringstream oss;
-  oss << "  " << leak_bytes << " bytes in ";
-  oss << num_leaks << " unreachable allocation" << plural(num_leaks);
-  oss << std::endl;
-  oss << "  ABI: '" ABI_STRING "'" << std::endl;
-  oss << std::endl;
-
-  for (auto it = leaks.begin(); it != leaks.end(); it++) {
-    oss << it->ToString(log_contents);
-    oss << std::endl;
-  }
-
-  return oss.str();
-}
-
-UnreachableMemoryInfo::~UnreachableMemoryInfo() {
-  // Clear the memory that holds the leaks, otherwise the next attempt to
-  // detect leaks may find the old data (for example in the jemalloc tcache)
-  // and consider all the leaks to be referenced.
-  memset(leaks.data(), 0, leaks.capacity() * sizeof(Leak));
-
-  std::vector<Leak> tmp;
-  leaks.swap(tmp);
-
-  // Disable and re-enable malloc to flush the jemalloc tcache to make sure
-  // there are no copies of the leaked pointer addresses there.
-  malloc_disable();
-  malloc_enable();
-}
-
-std::string GetUnreachableMemoryString(bool log_contents, size_t limit) {
-  UnreachableMemoryInfo info;
-  if (!GetUnreachableMemory(info, limit)) {
-    return "Failed to get unreachable memory\n"
-           "If you are trying to get unreachable memory from a system app\n"
-           "(like com.android.systemui), disable selinux first using\n"
-           "setenforce 0\n";
-  }
-
-  return info.ToString(log_contents);
-}
-
-}  // namespace android
-
-bool LogUnreachableMemory(bool log_contents, size_t limit) {
-  android::UnreachableMemoryInfo info;
-  if (!android::GetUnreachableMemory(info, limit)) {
-    return false;
-  }
-
-  for (auto it = info.leaks.begin(); it != info.leaks.end(); it++) {
-    MEM_ALOGE("%s", it->ToString(log_contents).c_str());
-  }
-  return true;
-}
-
-bool NoLeaks() {
-  android::UnreachableMemoryInfo info;
-  if (!android::GetUnreachableMemory(info, 0)) {
-    return false;
-  }
-
-  return info.num_leaks == 0;
-}
diff --git a/libmemunreachable/OWNERS b/libmemunreachable/OWNERS
deleted file mode 100644
index 9127a93..0000000
--- a/libmemunreachable/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-ccross@google.com
-cferris@google.com
diff --git a/libmemunreachable/ProcessMappings.cpp b/libmemunreachable/ProcessMappings.cpp
deleted file mode 100644
index 8e1be4c..0000000
--- a/libmemunreachable/ProcessMappings.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <android-base/unique_fd.h>
-#include <procinfo/process_map.h>
-
-#include "ProcessMappings.h"
-
-namespace android {
-
-struct ReadMapCallback {
-  ReadMapCallback(allocator::vector<Mapping>& mappings) : mappings_(mappings) {}
-
-  void operator()(uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t,
-                  const char* name) const {
-    mappings_.emplace_back(start, end, flags & PROT_READ, flags & PROT_WRITE, flags & PROT_EXEC,
-                           name);
-  }
-
-  allocator::vector<Mapping>& mappings_;
-};
-
-bool ProcessMappings(pid_t pid, allocator::vector<Mapping>& mappings) {
-  char map_buffer[1024];
-  snprintf(map_buffer, sizeof(map_buffer), "/proc/%d/maps", pid);
-  android::base::unique_fd fd(open(map_buffer, O_RDONLY));
-  if (fd == -1) {
-    return false;
-  }
-  allocator::string content(mappings.get_allocator());
-  ssize_t n;
-  while ((n = TEMP_FAILURE_RETRY(read(fd, map_buffer, sizeof(map_buffer)))) > 0) {
-    content.append(map_buffer, n);
-  }
-  ReadMapCallback callback(mappings);
-  return android::procinfo::ReadMapFileContent(&content[0], callback);
-}
-
-}  // namespace android
diff --git a/libmemunreachable/ProcessMappings.h b/libmemunreachable/ProcessMappings.h
deleted file mode 100644
index 94da69b..0000000
--- a/libmemunreachable/ProcessMappings.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_PROCESS_MAPPING_H_
-#define LIBMEMUNREACHABLE_PROCESS_MAPPING_H_
-
-#include <string.h>
-
-#include "Allocator.h"
-
-namespace android {
-
-struct Mapping {
-  uintptr_t begin;
-  uintptr_t end;
-  bool read;
-  bool write;
-  bool execute;
-  char name[96];
-
-  Mapping() {}
-  Mapping(uintptr_t begin, uintptr_t end, bool read, bool write, bool execute, const char* name)
-      : begin(begin), end(end), read(read), write(write), execute(execute) {
-    strlcpy(this->name, name, sizeof(this->name));
-  }
-};
-
-// This function is not re-entrant since it uses a static buffer for
-// the line data.
-bool ProcessMappings(pid_t pid, allocator::vector<Mapping>& mappings);
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_PROCESS_MAPPING_H_
diff --git a/libmemunreachable/PtracerThread.cpp b/libmemunreachable/PtracerThread.cpp
deleted file mode 100644
index d2fca49..0000000
--- a/libmemunreachable/PtracerThread.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2016 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 <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <sched.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "android-base/macros.h"
-
-#include "PtracerThread.h"
-#include "log.h"
-
-namespace android {
-
-class Stack {
- public:
-  explicit Stack(size_t size) : size_(size) {
-    int prot = PROT_READ | PROT_WRITE;
-    int flags = MAP_PRIVATE | MAP_ANONYMOUS;
-    page_size_ = sysconf(_SC_PAGE_SIZE);
-    size_ += page_size_ * 2;  // guard pages
-    base_ = mmap(NULL, size_, prot, flags, -1, 0);
-    if (base_ == MAP_FAILED) {
-      base_ = NULL;
-      size_ = 0;
-      return;
-    }
-    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, base_, size_, "libmemunreachable stack");
-    mprotect(base_, page_size_, PROT_NONE);
-    mprotect(top(), page_size_, PROT_NONE);
-  };
-  ~Stack() { munmap(base_, size_); };
-  void* top() {
-    return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(base_) + size_ - page_size_);
-  };
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Stack);
-
-  void* base_;
-  size_t size_;
-  size_t page_size_;
-};
-
-PtracerThread::PtracerThread(const std::function<int()>& func) : child_pid_(0) {
-  stack_ = std::make_unique<Stack>(PTHREAD_STACK_MIN);
-  if (stack_->top() == nullptr) {
-    MEM_LOG_ALWAYS_FATAL("failed to mmap child stack: %s", strerror(errno));
-  }
-
-  func_ = std::function<int()>{[&, func]() -> int {
-    // In the child thread, lock and unlock the mutex to wait for the parent
-    // to finish setting up for the child thread
-    std::unique_lock<std::mutex> lk(m_);
-    lk.unlock();
-    _exit(func());
-  }};
-}
-
-PtracerThread::~PtracerThread() {
-  Kill();
-  Join();
-  ClearTracer();
-  stack_ = nullptr;
-}
-
-bool PtracerThread::Start() {
-  std::unique_lock<std::mutex> lk(m_);
-
-  // Convert from void(*)(void*) to lambda with captures
-  auto proxy = [](void* arg) -> int {
-    prctl(PR_SET_NAME, "libmemunreachable ptrace thread");
-    return (*reinterpret_cast<std::function<int()>*>(arg))();
-  };
-
-  // See README.md for why we create the child process this way
-  child_pid_ = clone(proxy, stack_->top(), CLONE_VM | CLONE_FS | CLONE_FILES /*|CLONE_UNTRACED*/,
-                     reinterpret_cast<void*>(&func_));
-  if (child_pid_ < 0) {
-    MEM_ALOGE("failed to clone child: %s", strerror(errno));
-    return false;
-  }
-
-  SetTracer(child_pid_);
-
-  lk.unlock();
-
-  return true;
-}
-
-int PtracerThread::Join() {
-  if (child_pid_ == -1) {
-    return -1;
-  }
-  int status;
-  int ret = TEMP_FAILURE_RETRY(waitpid(child_pid_, &status, __WALL));
-  if (ret < 0) {
-    MEM_ALOGE("waitpid %d failed: %s", child_pid_, strerror(errno));
-    return -1;
-  }
-
-  child_pid_ = -1;
-
-  if (WIFEXITED(status)) {
-    return WEXITSTATUS(status);
-  } else if (WIFSIGNALED(status)) {
-    return -WTERMSIG(status);
-  } else {
-    MEM_ALOGE("unexpected status %x", status);
-    return -1;
-  }
-}
-
-void PtracerThread::Kill() {
-  if (child_pid_ == -1) {
-    return;
-  }
-
-  syscall(SYS_tkill, child_pid_, SIGKILL);
-}
-
-void PtracerThread::SetTracer(pid_t tracer_pid) {
-  prctl(PR_SET_PTRACER, tracer_pid);
-}
-
-void PtracerThread::ClearTracer() {
-  prctl(PR_SET_PTRACER, 0);
-}
-
-}  // namespace android
diff --git a/libmemunreachable/PtracerThread.h b/libmemunreachable/PtracerThread.h
deleted file mode 100644
index 4f9c420..0000000
--- a/libmemunreachable/PtracerThread.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_PTRACER_THREAD_H_
-#define LIBMEMUNREACHABLE_PTRACER_THREAD_H_
-
-#include <functional>
-#include <mutex>
-
-#include "android-base/macros.h"
-
-#include "Allocator.h"
-
-namespace android {
-
-class Stack;
-
-// PtracerThread is similar to std::thread, except that it creates a "thread"
-// that can ptrace the other threads.  The thread is actually a separate
-// process, with its own thread group, but shares address space and fds with
-// the parent.
-class PtracerThread {
- public:
-  explicit PtracerThread(const std::function<int()>& func);
-  ~PtracerThread();
-  bool Start();
-  int Join();
-
- private:
-  void SetTracer(pid_t);
-  void ClearTracer();
-  void Kill();
-  DISALLOW_COPY_AND_ASSIGN(PtracerThread);
-  std::unique_ptr<Stack> stack_;
-  std::function<int()> func_;
-  std::mutex m_;
-  pid_t child_pid_;
-};
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_PTRACER_THREAD_H_
diff --git a/libmemunreachable/README.md b/libmemunreachable/README.md
deleted file mode 100644
index 9cc0c9b..0000000
--- a/libmemunreachable/README.md
+++ /dev/null
@@ -1,92 +0,0 @@
-libmemunreachable
-================
-
-Introduction
---------------
-libmemunreachable is a zero-overhead native memory leak detector.  It uses an imprecise mark-and-sweep garbage collector pass over all native memory, reporting any unreachable blocks as leaks.  It is similar to the [Heap Checker from tcmalloc](http://htmlpreview.github.io/?https://github.com/gperftools/gperftools/blob/master/doc/heap_checker.html), but with a few key differences to remove the overhead.  Instead of instrumenting every call to malloc and free, it queries the allocator (jemalloc) for active allocations when leak detection is requested.  In addition, it performs a very short stop-the-world data collection on the main process, and then forks a copy of the process to perform the mark-and-sweep, minimizing disruption to the original process.
-
-In the default (zero-overhead) mode, the returned data on leaks is limited to the address, approximate (upper bound) size, and the the first 32 bytes of the contents of the leaked allocation.  If malloc_debug backtraces are enabled they will be included in the leak information, but backtracing allocations requires significant overhead.
-
-----------
-
-Usage
--------
-
-### In Android apps ###
-
-libmemunreachble is loaded by zygote and can be triggered with `dumpsys -t 600 meminfo --unreachable [process]`.
-
-To enable malloc\_debug backtraces on allocations for a single app process on a userdebug device, use:
-```
-adb root
-adb shell setprop libc.debug.malloc.program app_process
-adb shell setprop wrap.[process] "\$\@"
-adb shell setprop libc.debug.malloc.options backtrace=4
-```
-
-Kill and restart the app, trigger the leak, and then run `dumpsys -t 600 meminfo --unreachable [process]`.
-
-To disable malloc\_debug:
-```
-adb shell setprop libc.debug.malloc.options "''"
-adb shell setprop libc.debug.malloc.program "''"
-adb shell setprop wrap.[process]  "''"
-```
-
-### C interface ###
-
-#### `bool LogUnreachableMemory(bool log_contents, size_t limit)` ####
-Writes a description of leaked memory to the log.  A summary is always written, followed by details of up to `limit` leaks.  If `log_contents` is `true`, details include up to 32 bytes of the contents of each leaked allocation.
-Returns true if leak detection succeeded.
-
-#### `bool NoLeaks()` ####
-Returns `true` if no unreachable memory was found.
-
-### C++ interface ###
-
-#### `bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit = 100)` ####
-Updates an `UnreachableMemoryInfo` object with information on leaks, including details on up to `limit` leaks.  Returns true if leak detection succeeded.
-
-#### `std::string GetUnreachableMemoryString(bool log_contents = false, size_t limit = 100)` ####
-Returns a description of leaked memory.  A summary is always written, followed by details of up to `limit` leaks.  If `log_contents` is `true`, details include up to 32 bytes of the contents of each leaked allocation.
-Returns true if leak detection succeeded.
-
-Implementation
--------------------
-The sequence of steps required to perform a leak detection pass is divided into three processes - the original process, the collection process, and the sweeper process.
-
- 1. *Original process*: Leak detection is requested by calling `GetUnreachableMemory()`
- 2. Allocations are disabled using `malloc_disable()`
- 3. The collection process is spawned.  The collection process, created using clone, is similar to a normal `fork()` child process, except that it shares the address space of the parent - any writes by the original process are visible to the collection process, and vice-versa. If we forked instead of using clone, the address space might get out of sync with observed post-ptrace thread state, since it takes some time to pause the parent.
- 4. *Collection process*: All threads in the original process are paused with `ptrace()`.
- 5. Registers contents, active stack areas, and memory mapping information are collected.
- 6. *Original process*: Allocations are re-enabled using `malloc_enable()`, but all threads are still paused with `ptrace()`.
- 7. *Collection process*: The sweeper process is spawned using a normal `fork()`.  The sweeper process has a copy of all memory from the original process, including all the data collected by the collection process.
- 8. Collection process releases all threads from `ptrace` and exits
- 9. *Original process*: All threads continue, the thread that called `GetUnreachableMemory()` blocks waiting for leak data over a pipe.
- 10. *Sweeper process*: A list of all active allocations is produced by examining the memory mappings and calling `malloc_iterate()` on any heap mappings.
- 11. A list of all roots is produced from globals (.data and .bss sections of binaries), and registers and stacks from each thread.
- 12. The mark-and-sweep pass is performed starting from roots.
- 13. Unmarked allocations are sent over the pipe back to the original process.
-
-----------
-
-
-Components
----------------
-- `MemUnreachable.cpp`: Entry points, implements the sequencing described above.
-- `PtracerThread.cpp`: Used to clone the collection process with shared address space.
-- `ThreadCapture.cpp`: Pauses threads in the main process and collects register contents.
-- `ProcessMappings.cpp`: Collects snapshots of `/proc/pid/maps`.
-- `HeapWalker.cpp`: Performs the mark-and-sweep pass over active allocations.
-- `LeakPipe.cpp`: transfers data describing leaks from the sweeper process to the original process.
-
-
-Heap allocator requirements
-----------------------------------
-libmemunreachable requires a small interface to the allocator in order to collect information about active allocations.
-
- - `malloc_disable()`: prevent any thread from mutating internal allocator state.
- - `malloc enable()`: re-enable allocations in all threads.
- - `malloc_iterate()`: call a callback on each active allocation in a given heap region.
- - `malloc_backtrace()`: return the backtrace from when the allocation at the given address was allocated, if it was collected.
diff --git a/libmemunreachable/ScopedAlarm.h b/libmemunreachable/ScopedAlarm.h
deleted file mode 100644
index bb50b9e..0000000
--- a/libmemunreachable/ScopedAlarm.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_SCOPED_ALARM_H_
-#define LIBMEMUNREACHABLE_SCOPED_ALARM_H_
-
-#include <signal.h>
-#include <sys/time.h>
-
-#include <chrono>
-#include <functional>
-
-namespace android {
-
-class ScopedAlarm {
- public:
-  ScopedAlarm(std::chrono::microseconds us, std::function<void()> func) {
-    func_ = func;
-    struct sigaction oldact {};
-    struct sigaction act {};
-    act.sa_handler = [](int) { ScopedAlarm::func_(); };
-    sigaction(SIGALRM, &act, &oldact);
-
-    std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(us);
-    itimerval t = itimerval{};
-    t.it_value.tv_sec = s.count();
-    t.it_value.tv_usec = (us - s).count();
-    setitimer(ITIMER_REAL, &t, NULL);
-  }
-  ~ScopedAlarm() {
-    itimerval t = itimerval{};
-    setitimer(ITIMER_REAL, &t, NULL);
-    struct sigaction act {};
-    act.sa_handler = SIG_DFL;
-    sigaction(SIGALRM, &act, NULL);
-  }
-
- private:
-  static std::function<void()> func_;
-};
-
-}  // namespace android
-
-#endif
diff --git a/libmemunreachable/ScopedDisableMalloc.h b/libmemunreachable/ScopedDisableMalloc.h
deleted file mode 100644
index 655e826..0000000
--- a/libmemunreachable/ScopedDisableMalloc.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
-#define LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
-
-#include <memory>
-
-#include "android-base/macros.h"
-
-#include "ScopedAlarm.h"
-#include "bionic.h"
-#include "log.h"
-
-namespace android {
-
-class DisableMallocGuard {
- public:
-  DisableMallocGuard() : disabled_(false) {}
-  ~DisableMallocGuard() { Enable(); }
-
-  void Disable() {
-    if (!disabled_) {
-      malloc_disable();
-      disabled_ = true;
-    }
-  }
-
-  void Enable() {
-    if (disabled_) {
-      malloc_enable();
-      disabled_ = false;
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(DisableMallocGuard);
-  bool disabled_;
-};
-
-// Any calls to malloc or free from this thread will deadlock as long as this
-// object is in scope.  Calls to malloc from other threads may succeed (for
-// example if the allocation is satisfied out of the thread's tcache), or may
-// block until the object is destroyed.
-//
-// Don't call fork() while malloc is disabled, it needs the same locks held
-// here.
-class ScopedDisableMalloc {
- public:
-  ScopedDisableMalloc() { disable_malloc_.Disable(); }
-
-  ~ScopedDisableMalloc() { disable_malloc_.Enable(); }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedDisableMalloc);
-  DisableMallocGuard disable_malloc_;
-};
-
-class ScopedDisableMallocTimeout {
- public:
-  explicit ScopedDisableMallocTimeout(
-      std::chrono::milliseconds timeout = std::chrono::milliseconds(2000))
-      : timeout_(timeout), timed_out_(false), disable_malloc_() {
-    Disable();
-  }
-
-  ~ScopedDisableMallocTimeout() { Enable(); }
-
-  bool timed_out() { return timed_out_; }
-
-  void Enable() {
-    disable_malloc_.Enable();
-    alarm_ = nullptr;
-  }
-
-  void Disable() {
-    // set up the alarm before disabling malloc so unique_ptr can be used
-    alarm_ = std::make_unique<ScopedAlarm>(timeout_, [&]() {
-      disable_malloc_.Enable();
-      timed_out_ = true;
-    });
-
-    disable_malloc_.Disable();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ScopedDisableMallocTimeout);
-  std::chrono::milliseconds timeout_;
-  bool timed_out_;
-  std::unique_ptr<ScopedAlarm> alarm_;
-  DisableMallocGuard disable_malloc_;
-};
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_SCOPED_DISABLE_MALLOC_H_
diff --git a/libmemunreachable/ScopedPipe.h b/libmemunreachable/ScopedPipe.h
deleted file mode 100644
index b9dead5..0000000
--- a/libmemunreachable/ScopedPipe.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_SCOPED_PIPE_H_
-#define LIBMEMUNREACHABLE_SCOPED_PIPE_H_
-
-#include <unistd.h>
-
-#include "log.h"
-
-namespace android {
-
-class ScopedPipe {
- public:
-  ScopedPipe() : pipefd_{-1, -1} {
-    int ret = pipe2(pipefd_, O_CLOEXEC);
-    if (ret < 0) {
-      MEM_LOG_ALWAYS_FATAL("failed to open pipe");
-    }
-  }
-  ~ScopedPipe() { Close(); }
-
-  ScopedPipe(ScopedPipe&& other) noexcept {
-    SetReceiver(other.ReleaseReceiver());
-    SetSender(other.ReleaseSender());
-  }
-
-  ScopedPipe& operator=(ScopedPipe&& other) noexcept {
-    SetReceiver(other.ReleaseReceiver());
-    SetSender(other.ReleaseSender());
-    return *this;
-  }
-
-  void CloseReceiver() { close(ReleaseReceiver()); }
-
-  void CloseSender() { close(ReleaseSender()); }
-
-  void Close() {
-    CloseReceiver();
-    CloseSender();
-  }
-
-  int Receiver() { return pipefd_[0]; }
-  int Sender() { return pipefd_[1]; }
-
-  int ReleaseReceiver() {
-    int ret = Receiver();
-    SetReceiver(-1);
-    return ret;
-  }
-
-  int ReleaseSender() {
-    int ret = Sender();
-    SetSender(-1);
-    return ret;
-  }
-
- private:
-  void SetReceiver(int fd) { pipefd_[0] = fd; };
-  void SetSender(int fd) { pipefd_[1] = fd; };
-
-  int pipefd_[2];
-};
-
-}  // namespace android
-
-#endif
diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h
deleted file mode 100644
index ef4473f..0000000
--- a/libmemunreachable/ScopedSignalHandler.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_SCOPED_SIGNAL_HANDLER_H_
-#define LIBMEMUNREACHABLE_SCOPED_SIGNAL_HANDLER_H_
-
-#include <errno.h>
-#include <signal.h>
-
-#include <functional>
-
-#include "android-base/macros.h"
-
-#include "Allocator.h"
-#include "log.h"
-
-namespace android {
-
-class ScopedSignalHandler {
- public:
-  using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>;
-
-  explicit ScopedSignalHandler(Allocator<ScopedSignalHandler> allocator) : signal_(-1) {
-    if (handler_map_ == nullptr) {
-      Allocator<SignalFnMap> map_allocator = allocator;
-      handler_map_ = map_allocator.make_unique(allocator);
-    }
-  }
-  ~ScopedSignalHandler() { reset(); }
-
-  template <class F>
-  void install(int signal, F&& f) {
-    if (signal_ != -1) MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed");
-
-    if (handler_map_->find(signal) != handler_map_->end()) {
-      MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed for %d", signal);
-    }
-
-    (*handler_map_)[signal] =
-        SignalFn([=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); });
-
-    struct sigaction act {};
-    act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) {
-      ((*handler_map_)[signal])(signal, si, uctx);
-    };
-    act.sa_flags = SA_SIGINFO;
-
-    int ret = sigaction(signal, &act, &old_act_);
-    if (ret < 0) {
-      MEM_LOG_ALWAYS_FATAL("failed to install segfault handler: %s", strerror(errno));
-    }
-
-    signal_ = signal;
-  }
-
-  void reset() {
-    if (signal_ != -1) {
-      int ret = sigaction(signal_, &old_act_, NULL);
-      if (ret < 0) {
-        MEM_ALOGE("failed to uninstall segfault handler");
-      }
-
-      handler_map_->erase(signal_);
-      if (handler_map_->empty()) {
-        handler_map_.reset();
-      }
-      signal_ = -1;
-    }
-  }
-
- private:
-  using SignalFn = std::function<void(int, siginfo_t*, void*)>;
-  using SignalFnMap = allocator::unordered_map<int, SignalFn>;
-  DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
-  int signal_;
-  struct sigaction old_act_;
-  static Allocator<SignalFnMap>::unique_ptr handler_map_;
-};
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_SCOPED_SIGNAL_HANDLER_H_
diff --git a/libmemunreachable/Semaphore.h b/libmemunreachable/Semaphore.h
deleted file mode 100644
index cd73972..0000000
--- a/libmemunreachable/Semaphore.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_SEMAPHORE_H_
-#define LIBMEMUNREACHABLE_SEMAPHORE_H_
-
-#include <chrono>
-#include <mutex>
-
-#include "android-base/macros.h"
-
-namespace android {
-
-class Semaphore {
- public:
-  explicit Semaphore(int count = 0) : count_(count) {}
-  ~Semaphore() = default;
-
-  void Wait(std::chrono::milliseconds ms) {
-    std::unique_lock<std::mutex> lk(m_);
-    cv_.wait_for(lk, ms, [&] {
-      if (count_ > 0) {
-        count_--;
-        return true;
-      }
-      return false;
-    });
-  }
-  void Post() {
-    {
-      std::lock_guard<std::mutex> lk(m_);
-      count_++;
-    }
-    cv_.notify_one();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Semaphore);
-
-  int count_;
-  std::mutex m_;
-  std::condition_variable cv_;
-};
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_SEMAPHORE_H_
diff --git a/libmemunreachable/Tarjan.h b/libmemunreachable/Tarjan.h
deleted file mode 100644
index f3ab652..0000000
--- a/libmemunreachable/Tarjan.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// Based on system/update_engine/payload_generator/tarjan.cc
-
-#ifndef LIBMEMUNREACHABLE_TARJAN_H_
-#define LIBMEMUNREACHABLE_TARJAN_H_
-
-#include <assert.h>
-#include <algorithm>
-
-#include "Allocator.h"
-
-namespace android {
-
-template <class T>
-class Node {
- public:
-  allocator::set<Node<T>*> references_in;
-  allocator::set<Node<T>*> references_out;
-  size_t index;
-  size_t lowlink;
-
-  T* ptr;
-
-  Node(T* ptr, Allocator<Node> allocator)
-      : references_in(allocator), references_out(allocator), ptr(ptr){};
-  Node(Node&& rhs) noexcept = default;
-  void Edge(Node<T>* ref) {
-    references_out.emplace(ref);
-    ref->references_in.emplace(this);
-  }
-  template <class F>
-  void Foreach(F&& f) {
-    for (auto& node : references_out) {
-      f(node->ptr);
-    }
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(Node<T>);
-};
-
-template <class T>
-using Graph = allocator::vector<Node<T>*>;
-
-template <class T>
-using SCC = allocator::vector<Node<T>*>;
-
-template <class T>
-using SCCList = allocator::vector<SCC<T>>;
-
-template <class T>
-class TarjanAlgorithm {
- public:
-  explicit TarjanAlgorithm(Allocator<void> allocator)
-      : index_(0), stack_(allocator), components_(allocator) {}
-
-  void Execute(Graph<T>& graph, SCCList<T>& out);
-
- private:
-  static constexpr size_t UNDEFINED_INDEX = static_cast<size_t>(-1);
-  void Tarjan(Node<T>* vertex, Graph<T>& graph);
-
-  size_t index_;
-  allocator::vector<Node<T>*> stack_;
-  SCCList<T> components_;
-};
-
-template <class T>
-void TarjanAlgorithm<T>::Execute(Graph<T>& graph, SCCList<T>& out) {
-  stack_.clear();
-  components_.clear();
-  index_ = 0;
-  for (auto& it : graph) {
-    it->index = UNDEFINED_INDEX;
-    it->lowlink = UNDEFINED_INDEX;
-  }
-
-  for (auto& it : graph) {
-    if (it->index == UNDEFINED_INDEX) {
-      Tarjan(it, graph);
-    }
-  }
-  out.swap(components_);
-}
-
-template <class T>
-void TarjanAlgorithm<T>::Tarjan(Node<T>* vertex, Graph<T>& graph) {
-  assert(vertex->index == UNDEFINED_INDEX);
-  vertex->index = index_;
-  vertex->lowlink = index_;
-  index_++;
-  stack_.push_back(vertex);
-  for (auto& it : vertex->references_out) {
-    Node<T>* vertex_next = it;
-    if (vertex_next->index == UNDEFINED_INDEX) {
-      Tarjan(vertex_next, graph);
-      vertex->lowlink = std::min(vertex->lowlink, vertex_next->lowlink);
-    } else if (std::find(stack_.begin(), stack_.end(), vertex_next) != stack_.end()) {
-      vertex->lowlink = std::min(vertex->lowlink, vertex_next->index);
-    }
-  }
-  if (vertex->lowlink == vertex->index) {
-    SCC<T> component{components_.get_allocator()};
-    Node<T>* other_vertex;
-    do {
-      other_vertex = stack_.back();
-      stack_.pop_back();
-      component.push_back(other_vertex);
-    } while (other_vertex != vertex && !stack_.empty());
-
-    components_.emplace_back(component);
-  }
-}
-
-template <class T>
-void Tarjan(Graph<T>& graph, SCCList<T>& out) {
-  TarjanAlgorithm<T> tarjan{graph.get_allocator()};
-  tarjan.Execute(graph, out);
-}
-
-}  // namespace android
-
-#endif  // LIBMEMUNREACHABLE_TARJAN_H_
diff --git a/libmemunreachable/ThreadCapture.cpp b/libmemunreachable/ThreadCapture.cpp
deleted file mode 100644
index 45eb55d..0000000
--- a/libmemunreachable/ThreadCapture.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2016 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 "ThreadCapture.h"
-
-#include <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <sys/ptrace.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <vector>
-
-#include <android-base/unique_fd.h>
-
-#include "Allocator.h"
-#include "log.h"
-
-namespace android {
-
-// bionic interfaces used:
-// atoi
-// strlcat
-// writev
-
-// bionic interfaces reimplemented to avoid allocation:
-// getdents64
-
-// Convert a pid > 0 to a string.  sprintf might allocate, so we can't use it.
-// Returns a pointer somewhere in buf to a null terminated string, or NULL
-// on error.
-static char* pid_to_str(char* buf, size_t len, pid_t pid) {
-  if (pid <= 0) {
-    return nullptr;
-  }
-
-  char* ptr = buf + len - 1;
-  *ptr = 0;
-  while (pid > 0) {
-    ptr--;
-    if (ptr < buf) {
-      return nullptr;
-    }
-    *ptr = '0' + (pid % 10);
-    pid /= 10;
-  }
-
-  return ptr;
-}
-
-class ThreadCaptureImpl {
- public:
-  ThreadCaptureImpl(pid_t pid, Allocator<ThreadCaptureImpl>& allocator);
-  ~ThreadCaptureImpl() {}
-  bool ListThreads(TidList& tids);
-  bool CaptureThreads();
-  bool ReleaseThreads();
-  bool ReleaseThread(pid_t tid);
-  bool CapturedThreadInfo(ThreadInfoList& threads);
-  void InjectTestFunc(std::function<void(pid_t)>&& f) { inject_test_func_ = f; }
-
- private:
-  int CaptureThread(pid_t tid);
-  bool ReleaseThread(pid_t tid, unsigned int signal);
-  int PtraceAttach(pid_t tid);
-  void PtraceDetach(pid_t tid, unsigned int signal);
-  bool PtraceThreadInfo(pid_t tid, ThreadInfo& thread_info);
-
-  allocator::map<pid_t, unsigned int> captured_threads_;
-  Allocator<ThreadCaptureImpl> allocator_;
-  pid_t pid_;
-  std::function<void(pid_t)> inject_test_func_;
-};
-
-ThreadCaptureImpl::ThreadCaptureImpl(pid_t pid, Allocator<ThreadCaptureImpl>& allocator)
-    : captured_threads_(allocator), allocator_(allocator), pid_(pid) {}
-
-bool ThreadCaptureImpl::ListThreads(TidList& tids) {
-  tids.clear();
-
-  char pid_buf[11];
-  char path[256] = "/proc/";
-  char* pid_str = pid_to_str(pid_buf, sizeof(pid_buf), pid_);
-  if (!pid_str) {
-    return false;
-  }
-  strlcat(path, pid_str, sizeof(path));
-  strlcat(path, "/task", sizeof(path));
-
-  android::base::unique_fd fd(open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
-  if (fd == -1) {
-    MEM_ALOGE("failed to open %s: %s", path, strerror(errno));
-    return false;
-  }
-
-  struct linux_dirent64 {
-    uint64_t d_ino;
-    int64_t d_off;
-    uint16_t d_reclen;
-    char d_type;
-    char d_name[];
-  } __attribute((packed));
-  char dirent_buf[4096];
-  ssize_t nread;
-  do {
-    nread = syscall(SYS_getdents64, fd.get(), dirent_buf, sizeof(dirent_buf));
-    if (nread < 0) {
-      MEM_ALOGE("failed to get directory entries from %s: %s", path, strerror(errno));
-      return false;
-    } else if (nread > 0) {
-      ssize_t off = 0;
-      while (off < nread) {
-        linux_dirent64* dirent = reinterpret_cast<linux_dirent64*>(dirent_buf + off);
-        off += dirent->d_reclen;
-        pid_t tid = atoi(dirent->d_name);
-        if (tid <= 0) {
-          continue;
-        }
-        tids.push_back(tid);
-      }
-    }
-
-  } while (nread != 0);
-
-  return true;
-}
-
-bool ThreadCaptureImpl::CaptureThreads() {
-  TidList tids{allocator_};
-
-  bool found_new_thread;
-  do {
-    if (!ListThreads(tids)) {
-      ReleaseThreads();
-      return false;
-    }
-
-    found_new_thread = false;
-
-    for (auto it = tids.begin(); it != tids.end(); it++) {
-      auto captured = captured_threads_.find(*it);
-      if (captured == captured_threads_.end()) {
-        if (CaptureThread(*it) < 0) {
-          ReleaseThreads();
-          return false;
-        }
-        found_new_thread = true;
-      }
-    }
-  } while (found_new_thread);
-
-  return true;
-}
-
-// Detatches from a thread, delivering signal if nonzero, logs on error
-void ThreadCaptureImpl::PtraceDetach(pid_t tid, unsigned int signal) {
-  void* sig_ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(signal));
-  if (ptrace(PTRACE_DETACH, tid, NULL, sig_ptr) < 0 && errno != ESRCH) {
-    MEM_ALOGE("failed to detach from thread %d of process %d: %s", tid, pid_, strerror(errno));
-  }
-}
-
-// Attaches to and pauses thread.
-// Returns 1 on attach, 0 on tid not found, -1 and logs on error
-int ThreadCaptureImpl::PtraceAttach(pid_t tid) {
-  int ret = ptrace(PTRACE_SEIZE, tid, NULL, NULL);
-  if (ret < 0) {
-    MEM_ALOGE("failed to attach to thread %d of process %d: %s", tid, pid_, strerror(errno));
-    return -1;
-  }
-
-  if (inject_test_func_) {
-    inject_test_func_(tid);
-  }
-
-  if (ptrace(PTRACE_INTERRUPT, tid, 0, 0) < 0) {
-    if (errno == ESRCH) {
-      return 0;
-    } else {
-      MEM_ALOGE("failed to interrupt thread %d of process %d: %s", tid, pid_, strerror(errno));
-      PtraceDetach(tid, 0);
-      return -1;
-    }
-  }
-  return 1;
-}
-
-bool ThreadCaptureImpl::PtraceThreadInfo(pid_t tid, ThreadInfo& thread_info) {
-  thread_info.tid = tid;
-
-  const unsigned int max_num_regs = 128;  // larger than number of registers on any device
-  uintptr_t regs[max_num_regs];
-  struct iovec iovec;
-  iovec.iov_base = &regs;
-  iovec.iov_len = sizeof(regs);
-
-  if (ptrace(PTRACE_GETREGSET, tid, reinterpret_cast<void*>(NT_PRSTATUS), &iovec)) {
-    MEM_ALOGE("ptrace getregset for thread %d of process %d failed: %s", tid, pid_, strerror(errno));
-    return false;
-  }
-
-  unsigned int num_regs = iovec.iov_len / sizeof(uintptr_t);
-  thread_info.regs.assign(&regs[0], &regs[num_regs]);
-
-  const int sp =
-#if defined(__x86_64__)
-      offsetof(struct pt_regs, rsp) / sizeof(uintptr_t)
-#elif defined(__i386__)
-      offsetof(struct pt_regs, esp) / sizeof(uintptr_t)
-#elif defined(__arm__)
-      offsetof(struct pt_regs, ARM_sp) / sizeof(uintptr_t)
-#elif defined(__aarch64__)
-      offsetof(struct user_pt_regs, sp) / sizeof(uintptr_t)
-#elif defined(__mips__) || defined(__mips64__)
-      offsetof(struct pt_regs, regs[29]) / sizeof(uintptr_t)
-#else
-#error Unrecognized architecture
-#endif
-      ;
-
-  // TODO(ccross): use /proc/tid/status or /proc/pid/maps to get start_stack
-
-  thread_info.stack = std::pair<uintptr_t, uintptr_t>(regs[sp], 0);
-
-  return true;
-}
-
-int ThreadCaptureImpl::CaptureThread(pid_t tid) {
-  int ret = PtraceAttach(tid);
-  if (ret <= 0) {
-    return ret;
-  }
-
-  int status = 0;
-  if (TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL)) < 0) {
-    MEM_ALOGE("failed to wait for pause of thread %d of process %d: %s", tid, pid_, strerror(errno));
-    PtraceDetach(tid, 0);
-    return -1;
-  }
-
-  if (!WIFSTOPPED(status)) {
-    MEM_ALOGE("thread %d of process %d was not paused after waitpid, killed?", tid, pid_);
-    return 0;
-  }
-
-  unsigned int resume_signal = 0;
-
-  unsigned int signal = WSTOPSIG(status);
-  if ((status >> 16) == PTRACE_EVENT_STOP) {
-    switch (signal) {
-      case SIGSTOP:
-      case SIGTSTP:
-      case SIGTTIN:
-      case SIGTTOU:
-        // group-stop signals
-        break;
-      case SIGTRAP:
-        // normal ptrace interrupt stop
-        break;
-      default:
-        MEM_ALOGE("unexpected signal %d with PTRACE_EVENT_STOP for thread %d of process %d", signal,
-                  tid, pid_);
-        return -1;
-    }
-  } else {
-    // signal-delivery-stop
-    resume_signal = signal;
-  }
-
-  captured_threads_[tid] = resume_signal;
-  return 1;
-}
-
-bool ThreadCaptureImpl::ReleaseThread(pid_t tid) {
-  auto it = captured_threads_.find(tid);
-  if (it == captured_threads_.end()) {
-    return false;
-  }
-  return ReleaseThread(it->first, it->second);
-}
-
-bool ThreadCaptureImpl::ReleaseThread(pid_t tid, unsigned int signal) {
-  PtraceDetach(tid, signal);
-  return true;
-}
-
-bool ThreadCaptureImpl::ReleaseThreads() {
-  bool ret = true;
-  for (auto it = captured_threads_.begin(); it != captured_threads_.end();) {
-    if (ReleaseThread(it->first, it->second)) {
-      it = captured_threads_.erase(it);
-    } else {
-      it++;
-      ret = false;
-    }
-  }
-  return ret;
-}
-
-bool ThreadCaptureImpl::CapturedThreadInfo(ThreadInfoList& threads) {
-  threads.clear();
-
-  for (auto it = captured_threads_.begin(); it != captured_threads_.end(); it++) {
-    ThreadInfo t{0, allocator::vector<uintptr_t>(allocator_), std::pair<uintptr_t, uintptr_t>(0, 0)};
-    if (!PtraceThreadInfo(it->first, t)) {
-      return false;
-    }
-    threads.push_back(t);
-  }
-  return true;
-}
-
-ThreadCapture::ThreadCapture(pid_t pid, Allocator<ThreadCapture> allocator) {
-  Allocator<ThreadCaptureImpl> impl_allocator = allocator;
-  impl_ = impl_allocator.make_unique(pid, impl_allocator);
-}
-
-ThreadCapture::~ThreadCapture() {}
-
-bool ThreadCapture::ListThreads(TidList& tids) {
-  return impl_->ListThreads(tids);
-}
-
-bool ThreadCapture::CaptureThreads() {
-  return impl_->CaptureThreads();
-}
-
-bool ThreadCapture::ReleaseThreads() {
-  return impl_->ReleaseThreads();
-}
-
-bool ThreadCapture::ReleaseThread(pid_t tid) {
-  return impl_->ReleaseThread(tid);
-}
-
-bool ThreadCapture::CapturedThreadInfo(ThreadInfoList& threads) {
-  return impl_->CapturedThreadInfo(threads);
-}
-
-void ThreadCapture::InjectTestFunc(std::function<void(pid_t)>&& f) {
-  impl_->InjectTestFunc(std::forward<std::function<void(pid_t)>>(f));
-}
-
-}  // namespace android
diff --git a/libmemunreachable/ThreadCapture.h b/libmemunreachable/ThreadCapture.h
deleted file mode 100644
index 961cb60..0000000
--- a/libmemunreachable/ThreadCapture.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_THREAD_CAPTURE_H_
-#define LIBMEMUNREACHABLE_THREAD_CAPTURE_H_
-
-#include <utility>
-
-#include "Allocator.h"
-
-namespace android {
-
-struct ThreadInfo {
-  pid_t tid;
-  allocator::vector<uintptr_t> regs;
-  std::pair<uintptr_t, uintptr_t> stack;
-};
-
-using TidList = allocator::vector<pid_t>;
-using ThreadInfoList = allocator::vector<ThreadInfo>;
-
-class ThreadCaptureImpl;
-
-class ThreadCapture {
- public:
-  ThreadCapture(pid_t pid, Allocator<ThreadCapture> allocator);
-  ~ThreadCapture();
-
-  bool ListThreads(TidList& tids);
-  bool CaptureThreads();
-  bool ReleaseThreads();
-  bool ReleaseThread(pid_t tid);
-  bool CapturedThreadInfo(ThreadInfoList& threads);
-  void InjectTestFunc(std::function<void(pid_t)>&& f);
-
- private:
-  ThreadCapture(const ThreadCapture&) = delete;
-  void operator=(const ThreadCapture&) = delete;
-
-  Allocator<ThreadCaptureImpl>::unique_ptr impl_;
-};
-
-}  // namespace android
-
-#endif
diff --git a/libmemunreachable/bionic.h b/libmemunreachable/bionic.h
deleted file mode 100644
index dd1ec79..0000000
--- a/libmemunreachable/bionic.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_BIONIC_H_
-#define LIBMEMUNREACHABLE_BIONIC_H_
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-/* Exported from bionic */
-extern void malloc_disable();
-extern void malloc_enable();
-extern int malloc_iterate(uintptr_t base, size_t size,
-                          void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
-extern ssize_t malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
-
-__END_DECLS
-
-#endif  // LIBMEMUNREACHABLE_BIONIC_H_
diff --git a/libmemunreachable/include/memunreachable/memunreachable.h b/libmemunreachable/include/memunreachable/memunreachable.h
deleted file mode 100644
index c028eab..0000000
--- a/libmemunreachable/include/memunreachable/memunreachable.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
-#define LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
-
-#include <string.h>
-#include <sys/cdefs.h>
-
-#ifdef __cplusplus
-
-#include <string>
-#include <vector>
-
-namespace android {
-
-struct Leak {
-  uintptr_t begin;
-  size_t size;
-
-  size_t referenced_count;
-  size_t referenced_size;
-
-  size_t similar_count;
-  size_t similar_size;
-  size_t similar_referenced_count;
-  size_t similar_referenced_size;
-
-  size_t total_size;
-
-  static const size_t contents_length = 32;
-  char contents[contents_length];
-
-  struct Backtrace {
-    size_t num_frames;
-
-    static const size_t max_frames = 16;
-    uintptr_t frames[max_frames];
-  } backtrace;
-
-  std::string ToString(bool log_contents) const;
-};
-
-struct UnreachableMemoryInfo {
-  std::vector<Leak> leaks;
-  size_t num_leaks;
-  size_t leak_bytes;
-  size_t num_allocations;
-  size_t allocation_bytes;
-
-  UnreachableMemoryInfo() {}
-  ~UnreachableMemoryInfo();
-
-  std::string ToString(bool log_contents) const;
-};
-
-bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit = 100);
-
-std::string GetUnreachableMemoryString(bool log_contents = false, size_t limit = 100);
-
-}  // namespace android
-
-#endif
-
-__BEGIN_DECLS
-
-bool LogUnreachableMemory(bool log_contents, size_t limit);
-
-bool NoLeaks();
-
-__END_DECLS
-
-#endif  // LIBMEMUNREACHABLE_MEMUNREACHABLE_H_
diff --git a/libmemunreachable/log.h b/libmemunreachable/log.h
deleted file mode 100644
index 44c5f85..0000000
--- a/libmemunreachable/log.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 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 LIBMEMUNREACHABLE_LOG_H_
-#define LIBMEMUNREACHABLE_LOG_H_
-
-#define LOG_TAG "libmemunreachable"
-
-#if defined(__ANDROID__)
-
-#include <async_safe/log.h>
-
-#define MEM_ALOGE(...) async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, ##__VA_ARGS__)
-#define MEM_ALOGW(...) async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, ##__VA_ARGS__)
-#define MEM_ALOGI(...) async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, ##__VA_ARGS__)
-#define MEM_ALOGV_IMPL(...) async_safe_format_log(ANDROID_LOG_VERBOSE, LOG_TAG, ##__VA_ARGS__)
-
-#ifdef NDEBUG
-#define MEM_ALOGV(...)             \
-  do {                             \
-    if (0) {                       \
-      MEM_ALOGV_IMPL(__VA_ARGS__); \
-    }                              \
-  } while (0)
-#else
-#define MEM_ALOGV(...) MEM_ALOGV_IMPL(__VA_ARGS__)
-#endif
-
-#define MEM_LOG_ALWAYS_FATAL(...) async_safe_fatal(__VA_ARGS__)
-
-#else
-
-#include <log/log.h>
-
-#define MEM_ALOGW ALOGW
-#define MEM_ALOGE ALOGE
-#define MEM_ALOGV ALOGV
-#define MEM_ALOGI ALOGI
-
-#define MEM_LOG_ALWAYS_FATAL LOG_ALWAYS_FATAL
-
-#endif
-
-#endif  // LIBMEMUNREACHABLE_LOG_H_
diff --git a/libmemunreachable/tests/Allocator_test.cpp b/libmemunreachable/tests/Allocator_test.cpp
deleted file mode 100644
index 8991a7b..0000000
--- a/libmemunreachable/tests/Allocator_test.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2016 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 <Allocator.h>
-
-#include <ScopedDisableMalloc.h>
-#include <gtest/gtest.h>
-
-namespace android {
-
-std::function<void()> ScopedAlarm::func_;
-
-class AllocatorTest : public testing::Test {
- protected:
-  AllocatorTest() : heap(), disable_malloc_() {}
-  virtual void SetUp() { heap_count = 0; }
-  virtual void TearDown() {
-    ASSERT_EQ(heap_count, 0);
-    ASSERT_TRUE(heap.empty());
-    ASSERT_FALSE(disable_malloc_.timed_out());
-  }
-  Heap heap;
-
- private:
-  ScopedDisableMallocTimeout disable_malloc_;
-};
-
-TEST_F(AllocatorTest, simple) {
-  Allocator<char[100]> allocator(heap);
-  void* ptr = allocator.allocate();
-  ASSERT_TRUE(ptr != NULL);
-  allocator.deallocate(ptr);
-}
-
-TEST_F(AllocatorTest, multiple) {
-  Allocator<char[100]> allocator(heap);
-  void* ptr1 = allocator.allocate();
-  ASSERT_TRUE(ptr1 != NULL);
-  void* ptr2 = allocator.allocate();
-  ASSERT_TRUE(ptr2 != NULL);
-  ASSERT_NE(ptr1, ptr2);
-  allocator.deallocate(ptr1);
-  void* ptr3 = allocator.allocate();
-  ASSERT_EQ(ptr1, ptr3);
-  allocator.deallocate(ptr3);
-  allocator.deallocate(ptr2);
-}
-
-TEST_F(AllocatorTest, many) {
-  const int num = 4096;
-  const int size = 128;
-  Allocator<char[size]> allocator(heap);
-  void* ptr[num];
-  for (int i = 0; i < num; i++) {
-    ptr[i] = allocator.allocate();
-    memset(ptr[i], 0xaa, size);
-    *(reinterpret_cast<unsigned char*>(ptr[i])) = i;
-  }
-
-  for (int i = 0; i < num; i++) {
-    for (int j = 0; j < num; j++) {
-      if (i != j) {
-        ASSERT_NE(ptr[i], ptr[j]);
-      }
-    }
-  }
-
-  for (int i = 0; i < num; i++) {
-    ASSERT_EQ(*(reinterpret_cast<unsigned char*>(ptr[i])), i & 0xFF);
-    allocator.deallocate(ptr[i]);
-  }
-}
-
-TEST_F(AllocatorTest, large) {
-  const size_t size = 1024 * 1024;
-  Allocator<char[size]> allocator(heap);
-  void* ptr = allocator.allocate();
-  memset(ptr, 0xaa, size);
-  allocator.deallocate(ptr);
-}
-
-TEST_F(AllocatorTest, many_large) {
-  const int num = 128;
-  const int size = 1024 * 1024;
-  Allocator<char[size]> allocator(heap);
-  void* ptr[num];
-  for (int i = 0; i < num; i++) {
-    ptr[i] = allocator.allocate();
-    memset(ptr[i], 0xaa, size);
-    *(reinterpret_cast<unsigned char*>(ptr[i])) = i;
-  }
-
-  for (int i = 0; i < num; i++) {
-    ASSERT_EQ(*(reinterpret_cast<unsigned char*>(ptr[i])), i & 0xFF);
-    allocator.deallocate(ptr[i]);
-  }
-}
-
-TEST_F(AllocatorTest, copy) {
-  Allocator<char[100]> a(heap);
-  Allocator<char[200]> b = a;
-  Allocator<char[300]> c(b);
-  Allocator<char[100]> d(a);
-  Allocator<char[100]> e(heap);
-
-  ASSERT_EQ(a, b);
-  ASSERT_EQ(a, c);
-  ASSERT_EQ(a, d);
-  ASSERT_EQ(a, e);
-
-  void* ptr1 = a.allocate();
-  void* ptr2 = b.allocate();
-  void* ptr3 = c.allocate();
-  void* ptr4 = d.allocate();
-
-  b.deallocate(ptr1);
-  d.deallocate(ptr2);
-  a.deallocate(ptr3);
-  c.deallocate(ptr4);
-}
-
-TEST_F(AllocatorTest, stl_vector) {
-  auto v = allocator::vector<int>(Allocator<int>(heap));
-  for (int i = 0; i < 1024; i++) {
-    v.push_back(i);
-  }
-  for (int i = 0; i < 1024; i++) {
-    ASSERT_EQ(v[i], i);
-  }
-  v.clear();
-}
-
-TEST_F(AllocatorTest, stl_list) {
-  auto v = allocator::list<int>(Allocator<int>(heap));
-  for (int i = 0; i < 1024; i++) {
-    v.push_back(i);
-  }
-  int i = 0;
-  for (auto iter = v.begin(); iter != v.end(); iter++, i++) {
-    ASSERT_EQ(*iter, i);
-  }
-  v.clear();
-}
-
-TEST_F(AllocatorTest, shared) {
-  Allocator<int> allocator(heap);
-
-  Allocator<int>::shared_ptr ptr = allocator.make_shared(0);
-  {
-    auto ptr2 = ptr;  // NOLINT, test copy of ptr
-  }
-  ASSERT_NE(ptr, nullptr);
-}
-
-TEST_F(AllocatorTest, unique) {
-  Allocator<int> allocator(heap);
-
-  Allocator<int>::unique_ptr ptr = allocator.make_unique(0);
-
-  ASSERT_NE(ptr, nullptr);
-}
-
-}  // namespace android
diff --git a/libmemunreachable/tests/Binder_test.cpp b/libmemunreachable/tests/Binder_test.cpp
deleted file mode 100644
index eaf7652..0000000
--- a/libmemunreachable/tests/Binder_test.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2016 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 <signal.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
-#include <binder/ProcessState.h>
-
-#include <gtest/gtest.h>
-
-#include "Allocator.h"
-#include "Binder.h"
-
-namespace android {
-
-static const String16 service_name("test.libmemunreachable_binder");
-
-// Provides a service that will hold a strong reference to any remote binder
-// object, so that the test can verify that a remote strong reference is
-// visible to libmemunreachable.
-class BinderService : public BBinder {
- public:
-  BinderService() = default;
-  virtual ~BinderService() = default;
-
-  virtual status_t onTransact(uint32_t /*code*/, const Parcel& data, Parcel* reply,
-                              uint32_t /*flags*/ = 0) {
-    reply->writeStrongBinder(ref);
-    ref = data.readStrongBinder();
-    return 0;
-  }
-
- private:
-  sp<IBinder> ref;
-};
-
-class BinderObject : public BBinder {
- public:
-  BinderObject() = default;
-  ~BinderObject() = default;
-};
-
-// Forks a subprocess that registers a BinderService with the global binder
-// servicemanager.  Requires root permissions.
-class ServiceProcess {
- public:
-  ServiceProcess() : child_(0) {}
-  ~ServiceProcess() { Stop(); }
-
-  bool Run() {
-    pid_t ret = fork();
-    if (ret < 0) {
-      return false;
-    } else if (ret == 0) {
-      // child
-      _exit(Service());
-    } else {
-      // parent
-      child_ = ret;
-      return true;
-    }
-  }
-
-  bool Stop() {
-    if (child_ > 0) {
-      if (kill(child_, SIGTERM)) {
-        return false;
-      }
-      int status = 0;
-      if (TEMP_FAILURE_RETRY(waitpid(child_, &status, 0)) != child_) {
-        return false;
-      }
-      child_ = 0;
-      return WIFEXITED(status) && WEXITSTATUS(status) == 0;
-    }
-
-    return true;
-  }
-
-  int Service() {
-    sp<ProcessState> proc{ProcessState::self()};
-    sp<IServiceManager> sm = defaultServiceManager();
-    if (sm == nullptr) {
-      fprintf(stderr, "Failed to get service manager\n");
-      return 1;
-    }
-    // This step requires root permissions
-    if (sm->addService(service_name, new BinderService()) != OK) {
-      fprintf(stderr, "Failed to add test service\n");
-      return 1;
-    }
-    proc->startThreadPool();
-    pause();
-    return 0;
-  }
-
- private:
-  pid_t child_;
-};
-
-class MemunreachableBinderTest : public ::testing::Test {
- protected:
-  ServiceProcess service_process_;
-};
-
-// Tests that a local binder object with a remote strong reference is visible
-// through the libmemunreachable BinderReferences interface, which uses the
-// getBinderKernelReferences method in libbinder.  Starts a BinderService
-// through ServiceProcess as a remote service to hold the strong reference.
-TEST_F(MemunreachableBinderTest, binder) {
-  ASSERT_EQ(static_cast<uid_t>(0), getuid()) << "This test must be run as root.";
-
-  ServiceProcess service_process;
-  ASSERT_TRUE(service_process.Run());
-
-  sp<IServiceManager> sm = defaultServiceManager();
-  ASSERT_TRUE(sm != nullptr);
-
-  // A small sleep allows the service to start, which
-  // prevents a longer sleep in getService.
-  usleep(100000);
-
-  sp<IBinder> service = sm->getService(service_name);
-  ASSERT_TRUE(service != nullptr);
-
-  sp<IBinder> binder{new BinderObject()};
-
-  Parcel send;
-  Parcel reply;
-
-  send.writeStrongBinder(binder);
-  status_t rv = service->transact(0, send, &reply);
-  ASSERT_EQ(static_cast<status_t>(OK), rv);
-
-  Heap heap;
-  allocator::vector<uintptr_t> refs{heap};
-
-  ASSERT_TRUE(BinderReferences(refs));
-
-  bool found_ref = false;
-  for (auto ref : refs) {
-    if (ref == reinterpret_cast<uintptr_t>(binder.get())) {
-      found_ref = true;
-    }
-  }
-
-  ASSERT_TRUE(found_ref);
-}
-
-}  // namespace android
diff --git a/libmemunreachable/tests/DisableMalloc_test.cpp b/libmemunreachable/tests/DisableMalloc_test.cpp
deleted file mode 100644
index f446719..0000000
--- a/libmemunreachable/tests/DisableMalloc_test.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2016 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 <sys/time.h>
-
-#include <chrono>
-#include <functional>
-
-#include <ScopedDisableMalloc.h>
-#include <gtest/gtest.h>
-
-using namespace std::chrono_literals;
-
-namespace android {
-
-class DisableMallocTest : public ::testing::Test {
- protected:
-  void alarm(std::chrono::microseconds us) {
-    std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(us);
-    itimerval t = itimerval();
-    t.it_value.tv_sec = s.count();
-    t.it_value.tv_usec = (us - s).count();
-    setitimer(ITIMER_REAL, &t, NULL);
-  }
-};
-
-TEST_F(DisableMallocTest, reenable) {
-  ASSERT_EXIT(
-      {
-        alarm(100ms);
-        void* ptr1 = malloc(128);
-        ASSERT_NE(ptr1, nullptr);
-        free(ptr1);
-        { ScopedDisableMalloc disable_malloc; }
-        void* ptr2 = malloc(128);
-        ASSERT_NE(ptr2, nullptr);
-        free(ptr2);
-        _exit(1);
-      },
-      ::testing::ExitedWithCode(1), "");
-}
-
-TEST_F(DisableMallocTest, deadlock_allocate) {
-  ASSERT_DEATH(
-      {
-        void* ptr = malloc(128);
-        ASSERT_NE(ptr, nullptr);
-        free(ptr);
-        {
-          alarm(100ms);
-          ScopedDisableMalloc disable_malloc;
-          void* ptr = malloc(128);
-          ASSERT_NE(ptr, nullptr);
-          free(ptr);
-        }
-      },
-      "");
-}
-
-TEST_F(DisableMallocTest, deadlock_new) {
-  ASSERT_DEATH(
-      {
-        // C++ allows `new Foo` to be replaced with a stack allocation or merged
-        // with future `new Foo` expressions, provided certain conditions are
-        // met [expr.new/10]. None of this applies to `operator new(size_t)`.
-        void* ptr = ::operator new(1);
-        ASSERT_NE(ptr, nullptr);
-        ::operator delete(ptr);
-        {
-          alarm(100ms);
-          ScopedDisableMalloc disable_malloc;
-          void* ptr = ::operator new(1);
-          ASSERT_NE(ptr, nullptr);
-          ::operator delete(ptr);
-        }
-      },
-      "");
-}
-
-TEST_F(DisableMallocTest, deadlock_delete) {
-  ASSERT_DEATH(
-      {
-        void* ptr = ::operator new(1);
-        ASSERT_NE(ptr, nullptr);
-        {
-          alarm(250ms);
-          ScopedDisableMalloc disable_malloc;
-          ::operator delete(ptr);
-        }
-      },
-      "");
-}
-
-TEST_F(DisableMallocTest, deadlock_free) {
-  ASSERT_DEATH(
-      {
-        void* ptr = malloc(128);
-        ASSERT_NE(ptr, nullptr);
-        {
-          alarm(100ms);
-          ScopedDisableMalloc disable_malloc;
-          free(ptr);
-        }
-      },
-      "");
-}
-
-TEST_F(DisableMallocTest, deadlock_fork) {
-  ASSERT_DEATH({
-    {
-      alarm(100ms);
-      ScopedDisableMalloc disable_malloc;
-      fork();
-}
-}, "");
-}
-
-}  // namespace android
diff --git a/libmemunreachable/tests/HeapWalker_test.cpp b/libmemunreachable/tests/HeapWalker_test.cpp
deleted file mode 100644
index 9610cd6..0000000
--- a/libmemunreachable/tests/HeapWalker_test.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2016 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 <sys/mman.h>
-#include <unistd.h>
-
-#include "HeapWalker.h"
-
-#include <ScopedDisableMalloc.h>
-#include <gtest/gtest.h>
-#include "Allocator.h"
-
-namespace android {
-
-class HeapWalkerTest : public ::testing::Test {
- public:
-  HeapWalkerTest() : disable_malloc_(), heap_() {}
-
-  void TearDown() {
-    ASSERT_TRUE(heap_.empty());
-    if (!HasFailure()) {
-      ASSERT_FALSE(disable_malloc_.timed_out());
-    }
-  }
-
- protected:
-  ScopedDisableMallocTimeout disable_malloc_;
-  Heap heap_;
-};
-
-TEST_F(HeapWalkerTest, allocation) {
-  HeapWalker heap_walker(heap_);
-  ASSERT_TRUE(heap_walker.Allocation(3, 4));
-  ASSERT_TRUE(heap_walker.Allocation(2, 3));
-  ASSERT_TRUE(heap_walker.Allocation(4, 5));
-  ASSERT_TRUE(heap_walker.Allocation(6, 7));
-  ASSERT_TRUE(heap_walker.Allocation(0, 1));
-}
-
-TEST_F(HeapWalkerTest, overlap) {
-  HeapWalker heap_walker(heap_);
-  ASSERT_TRUE(heap_walker.Allocation(2, 3));
-  ASSERT_TRUE(heap_walker.Allocation(3, 4));
-  ASSERT_FALSE(heap_walker.Allocation(2, 3));
-  ASSERT_FALSE(heap_walker.Allocation(1, 3));
-  ASSERT_FALSE(heap_walker.Allocation(1, 4));
-  ASSERT_FALSE(heap_walker.Allocation(1, 5));
-  ASSERT_FALSE(heap_walker.Allocation(3, 4));
-  ASSERT_FALSE(heap_walker.Allocation(3, 5));
-  ASSERT_TRUE(heap_walker.Allocation(4, 5));
-  ASSERT_TRUE(heap_walker.Allocation(1, 2));
-}
-
-TEST_F(HeapWalkerTest, zero) {
-  HeapWalker heap_walker(heap_);
-  ASSERT_TRUE(heap_walker.Allocation(2, 2));
-  ASSERT_FALSE(heap_walker.Allocation(2, 2));
-  ASSERT_TRUE(heap_walker.Allocation(3, 3));
-  ASSERT_TRUE(heap_walker.Allocation(1, 1));
-  ASSERT_FALSE(heap_walker.Allocation(2, 3));
-}
-
-TEST_F(HeapWalkerTest, mapping) {
-  HeapWalker heap_walker(heap_);
-  heap_walker.Mapping(2, 3);
-  heap_walker.Mapping(4, 5);
-  ASSERT_TRUE(heap_walker.Allocation(2, 3));
-  ASSERT_TRUE(heap_walker.Allocation(4, 5));
-  // space between mappings is not checked, but could be in the future
-  ASSERT_TRUE(heap_walker.Allocation(3, 4));
-
-  // re-enable malloc, ASSERT_DEATH may allocate
-  disable_malloc_.Enable();
-  ASSERT_DEATH({ heap_walker.Allocation(1, 2); }, "0x1-0x2.*outside.*0x2-0x5");
-  ASSERT_DEATH({ heap_walker.Allocation(1, 3); }, "0x1-0x3.*outside.*0x2-0x5");
-  ASSERT_DEATH({ heap_walker.Allocation(4, 6); }, "0x4-0x6.*outside.*0x2-0x5");
-  ASSERT_DEATH({ heap_walker.Allocation(5, 6); }, "0x5-0x6.*outside.*0x2-0x5");
-  ASSERT_DEATH({ heap_walker.Allocation(1, 6); }, "0x1-0x6.*outside.*0x2-0x5");
-}
-
-#define buffer_begin(buffer) reinterpret_cast<uintptr_t>(buffer)
-#define buffer_end(buffer) (reinterpret_cast<uintptr_t>(buffer) + sizeof(buffer))
-
-TEST_F(HeapWalkerTest, leak) {
-  void* buffer1[16]{};
-  char buffer2[16]{};
-  buffer1[0] = &buffer2[0] - sizeof(void*);
-  buffer1[1] = &buffer2[15] + sizeof(void*);
-
-  HeapWalker heap_walker(heap_);
-  heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
-
-  ASSERT_EQ(true, heap_walker.DetectLeaks());
-
-  allocator::vector<Range> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(1U, num_leaks);
-  EXPECT_EQ(16U, leaked_bytes);
-  ASSERT_EQ(1U, leaked.size());
-  EXPECT_EQ(buffer_begin(buffer2), leaked[0].begin);
-  EXPECT_EQ(buffer_end(buffer2), leaked[0].end);
-}
-
-TEST_F(HeapWalkerTest, live) {
-  const int from_buffer_entries = 4;
-  const int to_buffer_bytes = 16;
-
-  for (int i = 0; i < from_buffer_entries; i++) {
-    for (int j = 0; j < to_buffer_bytes; j++) {
-      void* buffer1[from_buffer_entries]{};
-      char buffer2[to_buffer_bytes]{};
-      buffer1[i] = &buffer2[j];
-
-      HeapWalker heap_walker(heap_);
-      heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
-      heap_walker.Root(buffer_begin(buffer1), buffer_end(buffer1));
-
-      ASSERT_EQ(true, heap_walker.DetectLeaks());
-
-      allocator::vector<Range> leaked(heap_);
-      size_t num_leaks = SIZE_MAX;
-      size_t leaked_bytes = SIZE_MAX;
-      ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
-
-      EXPECT_EQ(0U, num_leaks);
-      EXPECT_EQ(0U, leaked_bytes);
-      EXPECT_EQ(0U, leaked.size());
-    }
-  }
-}
-
-TEST_F(HeapWalkerTest, unaligned) {
-  const int from_buffer_entries = 4;
-  const int to_buffer_bytes = 16;
-  void* buffer1[from_buffer_entries]{};
-  char buffer2[to_buffer_bytes]{};
-
-  buffer1[1] = &buffer2;
-
-  for (unsigned int i = 0; i < sizeof(uintptr_t); i++) {
-    for (unsigned int j = 0; j < sizeof(uintptr_t); j++) {
-      HeapWalker heap_walker(heap_);
-      heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
-      heap_walker.Root(buffer_begin(buffer1) + i, buffer_end(buffer1) - j);
-
-      ASSERT_EQ(true, heap_walker.DetectLeaks());
-
-      allocator::vector<Range> leaked(heap_);
-      size_t num_leaks = SIZE_MAX;
-      size_t leaked_bytes = SIZE_MAX;
-      ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
-
-      EXPECT_EQ(0U, num_leaks);
-      EXPECT_EQ(0U, leaked_bytes);
-      EXPECT_EQ(0U, leaked.size());
-    }
-  }
-}
-
-TEST_F(HeapWalkerTest, cycle) {
-  void* buffer1;
-  void* buffer2;
-
-  buffer1 = &buffer2;
-  buffer2 = &buffer1;
-
-  HeapWalker heap_walker(heap_);
-  heap_walker.Allocation(buffer_begin(buffer1), buffer_end(buffer1));
-  heap_walker.Allocation(buffer_begin(buffer2), buffer_end(buffer2));
-
-  ASSERT_EQ(true, heap_walker.DetectLeaks());
-
-  allocator::vector<Range> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(2U, num_leaks);
-  EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(2U, leaked.size());
-}
-
-TEST_F(HeapWalkerTest, segv) {
-  const size_t page_size = sysconf(_SC_PAGE_SIZE);
-  void* buffer1 = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-  ASSERT_NE(buffer1, nullptr);
-  void* buffer2;
-
-  buffer2 = &buffer1;
-
-  HeapWalker heap_walker(heap_);
-  heap_walker.Allocation(buffer_begin(buffer1), buffer_begin(buffer1) + page_size);
-  heap_walker.Root(buffer_begin(buffer2), buffer_end(buffer2));
-
-  ASSERT_EQ(true, heap_walker.DetectLeaks());
-
-  allocator::vector<Range> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, heap_walker.Leaked(leaked, 100, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(0U, num_leaks);
-  EXPECT_EQ(0U, leaked_bytes);
-  ASSERT_EQ(0U, leaked.size());
-}
-
-}  // namespace android
diff --git a/libmemunreachable/tests/LeakFolding_test.cpp b/libmemunreachable/tests/LeakFolding_test.cpp
deleted file mode 100644
index f5b3631..0000000
--- a/libmemunreachable/tests/LeakFolding_test.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (C) 2016 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 "LeakFolding.h"
-#include "HeapWalker.h"
-
-#include <ScopedDisableMalloc.h>
-#include <gtest/gtest.h>
-#include "Allocator.h"
-
-namespace android {
-
-class LeakFoldingTest : public ::testing::Test {
- public:
-  LeakFoldingTest() : disable_malloc_(), heap_() {}
-
-  void TearDown() {
-    ASSERT_TRUE(heap_.empty());
-    if (!HasFailure()) {
-      ASSERT_FALSE(disable_malloc_.timed_out());
-    }
-  }
-
- protected:
-  ScopedDisableMallocTimeout disable_malloc_;
-  Heap heap_;
-};
-
-#define buffer_begin(buffer) reinterpret_cast<uintptr_t>(&(buffer)[0])
-#define buffer_end(buffer) (reinterpret_cast<uintptr_t>(&(buffer)[0]) + sizeof(buffer))
-#define ALLOCATION(heap_walker, buffer) \
-  ASSERT_EQ(true, (heap_walker).Allocation(buffer_begin(buffer), buffer_end(buffer)))
-
-TEST_F(LeakFoldingTest, one) {
-  void* buffer1[1] = {nullptr};
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(1U, num_leaks);
-  EXPECT_EQ(sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(1U, leaked.size());
-  EXPECT_EQ(0U, leaked[0].referenced_count);
-  EXPECT_EQ(0U, leaked[0].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, two) {
-  void* buffer1[1] = {nullptr};
-  void* buffer2[1] = {nullptr};
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(2U, num_leaks);
-  EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(2U, leaked.size());
-  EXPECT_EQ(0U, leaked[0].referenced_count);
-  EXPECT_EQ(0U, leaked[0].referenced_size);
-  EXPECT_EQ(0U, leaked[1].referenced_count);
-  EXPECT_EQ(0U, leaked[1].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, dominator) {
-  void* buffer1[1];
-  void* buffer2[1] = {nullptr};
-
-  buffer1[0] = buffer2;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(2U, num_leaks);
-  EXPECT_EQ(2 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(1U, leaked.size());
-  EXPECT_EQ(1U, leaked[0].referenced_count);
-  EXPECT_EQ(sizeof(uintptr_t), leaked[0].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, cycle) {
-  void* buffer1[1];
-  void* buffer2[1];
-  void* buffer3[1];
-
-  buffer1[0] = buffer2;
-  buffer2[0] = buffer3;
-  buffer3[0] = buffer2;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-  ALLOCATION(heap_walker, buffer3);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(3U, num_leaks);
-  EXPECT_EQ(3 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(1U, leaked.size());
-  EXPECT_EQ(2U, leaked[0].referenced_count);
-  EXPECT_EQ(2 * sizeof(uintptr_t), leaked[0].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, dominator_cycle) {
-  void* buffer1[2] = {nullptr, nullptr};
-  void* buffer2[2];
-  void* buffer3[1] = {nullptr};
-
-  buffer1[0] = &buffer2;
-  buffer2[0] = &buffer1;
-  buffer2[1] = &buffer3;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-  ALLOCATION(heap_walker, buffer3);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(3U, num_leaks);
-  EXPECT_EQ(5 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(2U, leaked.size());
-
-  EXPECT_EQ(2U, leaked[0].referenced_count);
-  EXPECT_EQ(3 * sizeof(uintptr_t), leaked[0].referenced_size);
-  EXPECT_EQ(2U, leaked[1].referenced_count);
-  EXPECT_EQ(3 * sizeof(uintptr_t), leaked[1].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, two_cycles) {
-  void* buffer1[1];
-  void* buffer2[1];
-  void* buffer3[1];
-  void* buffer4[1];
-  void* buffer5[1];
-  void* buffer6[1];
-
-  buffer1[0] = buffer3;
-  buffer2[0] = buffer5;
-  buffer3[0] = buffer4;
-  buffer4[0] = buffer3;
-  buffer5[0] = buffer6;
-  buffer6[0] = buffer5;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-  ALLOCATION(heap_walker, buffer3);
-  ALLOCATION(heap_walker, buffer4);
-  ALLOCATION(heap_walker, buffer5);
-  ALLOCATION(heap_walker, buffer6);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(6U, num_leaks);
-  EXPECT_EQ(6 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(2U, leaked.size());
-  EXPECT_EQ(2U, leaked[0].referenced_count);
-  EXPECT_EQ(2 * sizeof(uintptr_t), leaked[0].referenced_size);
-  EXPECT_EQ(2U, leaked[1].referenced_count);
-  EXPECT_EQ(2 * sizeof(uintptr_t), leaked[1].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, two_dominator_cycles) {
-  void* buffer1[1];
-  void* buffer2[1];
-  void* buffer3[1];
-  void* buffer4[1];
-
-  buffer1[0] = buffer2;
-  buffer2[0] = buffer1;
-  buffer3[0] = buffer4;
-  buffer4[0] = buffer3;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-  ALLOCATION(heap_walker, buffer3);
-  ALLOCATION(heap_walker, buffer4);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(4U, num_leaks);
-  EXPECT_EQ(4 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(4U, leaked.size());
-  EXPECT_EQ(1U, leaked[0].referenced_count);
-  EXPECT_EQ(sizeof(uintptr_t), leaked[0].referenced_size);
-  EXPECT_EQ(1U, leaked[1].referenced_count);
-  EXPECT_EQ(sizeof(uintptr_t), leaked[1].referenced_size);
-  EXPECT_EQ(1U, leaked[2].referenced_count);
-  EXPECT_EQ(sizeof(uintptr_t), leaked[2].referenced_size);
-  EXPECT_EQ(1U, leaked[3].referenced_count);
-  EXPECT_EQ(sizeof(uintptr_t), leaked[3].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, giant_dominator_cycle) {
-  const size_t n = 1000;
-  void* buffer[n];
-
-  HeapWalker heap_walker(heap_);
-
-  for (size_t i = 0; i < n; i++) {
-    ASSERT_TRUE(heap_walker.Allocation(reinterpret_cast<uintptr_t>(&buffer[i]),
-                                       reinterpret_cast<uintptr_t>(&buffer[i + 1])));
-  }
-
-  for (size_t i = 0; i < n - 1; i++) {
-    buffer[i] = &buffer[i + 1];
-  }
-  buffer[n - 1] = &buffer[0];
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(n, num_leaks);
-  EXPECT_EQ(n * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(1000U, leaked.size());
-  EXPECT_EQ(n - 1, leaked[0].referenced_count);
-  EXPECT_EQ((n - 1) * sizeof(uintptr_t), leaked[0].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, giant_cycle) {
-  const size_t n = 1000;
-  void* buffer[n];
-  void* buffer1[1];
-
-  HeapWalker heap_walker(heap_);
-
-  for (size_t i = 0; i < n - 1; i++) {
-    buffer[i] = &buffer[i + 1];
-  }
-  buffer[n - 1] = &buffer[0];
-
-  buffer1[0] = &buffer[0];
-
-  for (size_t i = 0; i < n; i++) {
-    ASSERT_TRUE(heap_walker.Allocation(reinterpret_cast<uintptr_t>(&buffer[i]),
-                                       reinterpret_cast<uintptr_t>(&buffer[i + 1])));
-  }
-
-  ALLOCATION(heap_walker, buffer1);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(n + 1, num_leaks);
-  EXPECT_EQ((n + 1) * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(1U, leaked.size());
-  EXPECT_EQ(n, leaked[0].referenced_count);
-  EXPECT_EQ(n * sizeof(uintptr_t), leaked[0].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, multipath) {
-  void* buffer1[2];
-  void* buffer2[1];
-  void* buffer3[1];
-  void* buffer4[1] = {nullptr};
-
-  //    1
-  //   / \
-  //  v   v
-  //  2   3
-  //   \ /
-  //    v
-  //    4
-
-  buffer1[0] = &buffer2;
-  buffer1[1] = &buffer3;
-  buffer2[0] = &buffer4;
-  buffer3[0] = &buffer4;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-  ALLOCATION(heap_walker, buffer3);
-  ALLOCATION(heap_walker, buffer4);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(4U, num_leaks);
-  EXPECT_EQ(5 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(1U, leaked.size());
-  EXPECT_EQ(3U, leaked[0].referenced_count);
-  EXPECT_EQ(3 * sizeof(uintptr_t), leaked[0].referenced_size);
-}
-
-TEST_F(LeakFoldingTest, multicycle) {
-  void* buffer1[2]{};
-  void* buffer2[2]{};
-  void* buffer3[2]{};
-  void* buffer4[2]{};
-
-  //    1
-  //   / ^
-  //  v   \
-  //  2 -> 3
-  //   \   ^
-  //    v /
-  //     4
-
-  buffer1[0] = &buffer2;
-  buffer2[0] = &buffer3;
-  buffer2[1] = &buffer4;
-  buffer3[0] = &buffer1;
-  buffer4[0] = &buffer3;
-
-  HeapWalker heap_walker(heap_);
-
-  ALLOCATION(heap_walker, buffer1);
-  ALLOCATION(heap_walker, buffer2);
-  ALLOCATION(heap_walker, buffer3);
-  ALLOCATION(heap_walker, buffer4);
-
-  LeakFolding folding(heap_, heap_walker);
-
-  ASSERT_TRUE(folding.FoldLeaks());
-
-  allocator::vector<LeakFolding::Leak> leaked(heap_);
-  size_t num_leaks = 0;
-  size_t leaked_bytes = 0;
-  ASSERT_EQ(true, folding.Leaked(leaked, &num_leaks, &leaked_bytes));
-
-  EXPECT_EQ(4U, num_leaks);
-  EXPECT_EQ(8 * sizeof(uintptr_t), leaked_bytes);
-  ASSERT_EQ(4U, leaked.size());
-  EXPECT_EQ(3U, leaked[0].referenced_count);
-  EXPECT_EQ(6 * sizeof(uintptr_t), leaked[0].referenced_size);
-  EXPECT_EQ(3U, leaked[1].referenced_count);
-  EXPECT_EQ(6 * sizeof(uintptr_t), leaked[1].referenced_size);
-  EXPECT_EQ(3U, leaked[2].referenced_count);
-  EXPECT_EQ(6 * sizeof(uintptr_t), leaked[2].referenced_size);
-  EXPECT_EQ(3U, leaked[3].referenced_count);
-  EXPECT_EQ(6 * sizeof(uintptr_t), leaked[3].referenced_size);
-}
-
-}  // namespace android
diff --git a/libmemunreachable/tests/MemUnreachable_test.cpp b/libmemunreachable/tests/MemUnreachable_test.cpp
deleted file mode 100644
index bba0c6d..0000000
--- a/libmemunreachable/tests/MemUnreachable_test.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2016 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 <fcntl.h>
-#include <stdlib.h>
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#include <gtest/gtest.h>
-
-#include <memunreachable/memunreachable.h>
-
-#include "bionic.h"
-
-namespace android {
-
-class HiddenPointer {
- public:
-  // Since we're doing such a good job of hiding it, the static analyzer
-  // thinks that we're leaking this `malloc`. This is probably related to
-  // https://bugs.llvm.org/show_bug.cgi?id=34198. NOLINTNEXTLINE
-  explicit HiddenPointer(size_t size = 256) { Set(malloc(size)); }
-  ~HiddenPointer() { Free(); }
-  void* Get() { return reinterpret_cast<void*>(~ptr_); }
-  void Free() {
-    free(Get());
-    Set(nullptr);
-  }
-
- private:
-  void Set(void* ptr) { ptr_ = ~reinterpret_cast<uintptr_t>(ptr); }
-  volatile uintptr_t ptr_;
-};
-
-// Trick the compiler into thinking a value on the stack is still referenced.
-static void Ref(void** ptr) {
-  write(0, ptr, 0);
-}
-
-class MemunreachableTest : public ::testing::Test {
- protected:
-  virtual void SetUp() {
-    CleanStack(8192);
-    CleanTcache();
-  }
-
-  virtual void TearDown() {
-    CleanStack(8192);
-    CleanTcache();
-  }
-
-  // Allocate a buffer on the stack and zero it to make sure there are no
-  // stray pointers from old test runs.
-  void __attribute__((noinline)) CleanStack(size_t size) {
-    void* buf = alloca(size);
-    memset(buf, 0, size);
-    Ref(&buf);
-  }
-
-  // Disable and re-enable malloc to flush the jemalloc tcache to make sure
-  // there are stray pointers from old test runs there.
-  void CleanTcache() {
-    malloc_disable();
-    malloc_enable();
-  }
-};
-
-TEST_F(MemunreachableTest, clean) {
-  UnreachableMemoryInfo info;
-
-  ASSERT_TRUE(LogUnreachableMemory(true, 100));
-
-  ASSERT_TRUE(GetUnreachableMemory(info));
-  ASSERT_EQ(0U, info.leaks.size());
-}
-
-TEST_F(MemunreachableTest, stack) {
-  HiddenPointer hidden_ptr;
-
-  {
-    void* ptr = hidden_ptr.Get();
-    Ref(&ptr);
-
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-
-    ptr = nullptr;
-  }
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(1U, info.leaks.size());
-  }
-
-  hidden_ptr.Free();
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-}
-
-void* g_ptr;
-
-TEST_F(MemunreachableTest, global) {
-  HiddenPointer hidden_ptr;
-
-  g_ptr = hidden_ptr.Get();
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-
-  g_ptr = nullptr;
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(1U, info.leaks.size());
-  }
-
-  hidden_ptr.Free();
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-}
-
-TEST_F(MemunreachableTest, tls) {
-  HiddenPointer hidden_ptr;
-  pthread_key_t key;
-  pthread_key_create(&key, nullptr);
-
-  pthread_setspecific(key, hidden_ptr.Get());
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-
-  pthread_setspecific(key, nullptr);
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(1U, info.leaks.size());
-  }
-
-  hidden_ptr.Free();
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-
-  pthread_key_delete(key);
-}
-
-TEST_F(MemunreachableTest, twice) {
-  HiddenPointer hidden_ptr;
-
-  {
-    void* ptr = hidden_ptr.Get();
-    Ref(&ptr);
-
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-
-    ptr = nullptr;
-  }
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(1U, info.leaks.size());
-  }
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(1U, info.leaks.size());
-  }
-
-  hidden_ptr.Free();
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-}
-
-TEST_F(MemunreachableTest, log) {
-  HiddenPointer hidden_ptr;
-
-  ASSERT_TRUE(LogUnreachableMemory(true, 100));
-
-  hidden_ptr.Free();
-
-  {
-    UnreachableMemoryInfo info;
-
-    ASSERT_TRUE(GetUnreachableMemory(info));
-    ASSERT_EQ(0U, info.leaks.size());
-  }
-}
-
-TEST_F(MemunreachableTest, notdumpable) {
-  if (getuid() == 0) {
-    // TODO(ccross): make this a skipped test when gtest supports them
-    printf("[ SKIP     ] Not testable when running as root\n");
-    return;
-  }
-
-  ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 0));
-
-  HiddenPointer hidden_ptr;
-
-  EXPECT_FALSE(LogUnreachableMemory(true, 100));
-
-  ASSERT_EQ(0, prctl(PR_SET_DUMPABLE, 1));
-}
-
-TEST_F(MemunreachableTest, leak_lots) {
-  std::vector<HiddenPointer> hidden_ptrs;
-  hidden_ptrs.resize(1024);
-
-  ASSERT_TRUE(LogUnreachableMemory(true, 100));
-}
-
-}  // namespace android
diff --git a/libmemunreachable/tests/ThreadCapture_test.cpp b/libmemunreachable/tests/ThreadCapture_test.cpp
deleted file mode 100644
index 933d65a..0000000
--- a/libmemunreachable/tests/ThreadCapture_test.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2016 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 "ThreadCapture.h"
-
-#include <fcntl.h>
-#include <pthread.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <functional>
-#include <memory>
-#include <thread>
-
-#include <gtest/gtest.h>
-
-#include "Allocator.h"
-#include "ScopedDisableMalloc.h"
-#include "ScopedPipe.h"
-
-#include <android-base/threads.h>
-
-using namespace std::chrono_literals;
-
-namespace android {
-
-class ThreadListTest : public ::testing::TestWithParam<int> {
- public:
-  ThreadListTest() : stop_(false) {}
-
-  ~ThreadListTest() {
-    // pthread_join may return before the entry in /proc/pid/task/ is gone,
-    // loop until ListThreads only finds the main thread so the next test
-    // doesn't fail.
-    WaitForThreads();
-  }
-
-  virtual void TearDown() { ASSERT_TRUE(heap.empty()); }
-
- protected:
-  template <class Function>
-  void StartThreads(unsigned int threads, Function&& func) {
-    threads_.reserve(threads);
-    tids_.reserve(threads);
-    for (unsigned int i = 0; i < threads; i++) {
-      threads_.emplace_back([&, threads, this]() {
-        {
-          std::lock_guard<std::mutex> lk(m_);
-          tids_.push_back(gettid());
-          if (tids_.size() == threads) {
-            cv_start_.notify_one();
-          }
-        }
-
-        func();
-
-        {
-          std::unique_lock<std::mutex> lk(m_);
-          cv_stop_.wait(lk, [&] { return stop_; });
-        }
-      });
-    }
-
-    {
-      std::unique_lock<std::mutex> lk(m_);
-      cv_start_.wait(lk, [&] { return tids_.size() == threads; });
-    }
-  }
-
-  void StopThreads() {
-    {
-      std::lock_guard<std::mutex> lk(m_);
-      stop_ = true;
-    }
-    cv_stop_.notify_all();
-
-    for (auto i = threads_.begin(); i != threads_.end(); i++) {
-      i->join();
-    }
-    threads_.clear();
-    tids_.clear();
-  }
-
-  std::vector<pid_t>& tids() { return tids_; }
-
-  Heap heap;
-
- private:
-  void WaitForThreads() {
-    auto tids = TidList{heap};
-    ThreadCapture thread_capture{getpid(), heap};
-
-    for (unsigned int i = 0; i < 100; i++) {
-      EXPECT_TRUE(thread_capture.ListThreads(tids));
-      if (tids.size() == 1) {
-        break;
-      }
-      std::this_thread::sleep_for(10ms);
-    }
-    EXPECT_EQ(1U, tids.size());
-  }
-
-  std::mutex m_;
-  std::condition_variable cv_start_;
-  std::condition_variable cv_stop_;
-  bool stop_;
-  std::vector<pid_t> tids_;
-
-  std::vector<std::thread> threads_;
-};
-
-TEST_F(ThreadListTest, list_one) {
-  ScopedDisableMallocTimeout disable_malloc;
-
-  ThreadCapture thread_capture(getpid(), heap);
-
-  auto expected_tids = allocator::vector<pid_t>(1, getpid(), heap);
-  auto list_tids = allocator::vector<pid_t>(heap);
-
-  ASSERT_TRUE(thread_capture.ListThreads(list_tids));
-
-  ASSERT_EQ(expected_tids, list_tids);
-
-  if (!HasFailure()) {
-    ASSERT_FALSE(disable_malloc.timed_out());
-  }
-}
-
-TEST_P(ThreadListTest, list_some) {
-  const unsigned int threads = GetParam() - 1;
-
-  StartThreads(threads, []() {});
-  std::vector<pid_t> expected_tids = tids();
-  expected_tids.push_back(getpid());
-
-  auto list_tids = allocator::vector<pid_t>(heap);
-
-  {
-    ScopedDisableMallocTimeout disable_malloc;
-
-    ThreadCapture thread_capture(getpid(), heap);
-
-    ASSERT_TRUE(thread_capture.ListThreads(list_tids));
-
-    if (!HasFailure()) {
-      ASSERT_FALSE(disable_malloc.timed_out());
-    }
-  }
-
-  StopThreads();
-
-  std::sort(list_tids.begin(), list_tids.end());
-  std::sort(expected_tids.begin(), expected_tids.end());
-
-  ASSERT_EQ(expected_tids.size(), list_tids.size());
-  EXPECT_TRUE(std::equal(expected_tids.begin(), expected_tids.end(), list_tids.begin()));
-}
-
-INSTANTIATE_TEST_CASE_P(ThreadListTest, ThreadListTest, ::testing::Values(1, 2, 10, 1024));
-
-class ThreadCaptureTest : public ThreadListTest {
- public:
-  ThreadCaptureTest() {}
-  ~ThreadCaptureTest() {}
-  void Fork(std::function<void()>&& child_init, std::function<void()>&& child_cleanup,
-            std::function<void(pid_t)>&& parent) {
-    ScopedPipe start_pipe;
-    ScopedPipe stop_pipe;
-
-    int pid = fork();
-
-    if (pid == 0) {
-      // child
-      child_init();
-      EXPECT_EQ(1, TEMP_FAILURE_RETRY(write(start_pipe.Sender(), "+", 1))) << strerror(errno);
-      char buf;
-      EXPECT_EQ(1, TEMP_FAILURE_RETRY(read(stop_pipe.Receiver(), &buf, 1))) << strerror(errno);
-      child_cleanup();
-      _exit(0);
-    } else {
-      // parent
-      ASSERT_GT(pid, 0);
-      char buf;
-      ASSERT_EQ(1, TEMP_FAILURE_RETRY(read(start_pipe.Receiver(), &buf, 1))) << strerror(errno);
-
-      parent(pid);
-
-      ASSERT_EQ(1, TEMP_FAILURE_RETRY(write(stop_pipe.Sender(), "+", 1))) << strerror(errno);
-      siginfo_t info{};
-      ASSERT_EQ(0, TEMP_FAILURE_RETRY(waitid(P_PID, pid, &info, WEXITED))) << strerror(errno);
-    }
-  }
-};
-
-TEST_P(ThreadCaptureTest, capture_some) {
-  const unsigned int threads = GetParam();
-
-  Fork(
-      [&]() {
-        // child init
-        StartThreads(threads - 1, []() {});
-      },
-      [&]() {
-        // child cleanup
-        StopThreads();
-      },
-      [&](pid_t child) {
-        // parent
-        ASSERT_GT(child, 0);
-
-        {
-          ScopedDisableMallocTimeout disable_malloc;
-
-          ThreadCapture thread_capture(child, heap);
-          auto list_tids = allocator::vector<pid_t>(heap);
-
-          ASSERT_TRUE(thread_capture.ListThreads(list_tids));
-          ASSERT_EQ(threads, list_tids.size());
-
-          ASSERT_TRUE(thread_capture.CaptureThreads());
-
-          auto thread_info = allocator::vector<ThreadInfo>(heap);
-          ASSERT_TRUE(thread_capture.CapturedThreadInfo(thread_info));
-          ASSERT_EQ(threads, thread_info.size());
-          ASSERT_TRUE(thread_capture.ReleaseThreads());
-
-          if (!HasFailure()) {
-            ASSERT_FALSE(disable_malloc.timed_out());
-          }
-        }
-      });
-}
-
-INSTANTIATE_TEST_CASE_P(ThreadCaptureTest, ThreadCaptureTest, ::testing::Values(1, 2, 10, 1024));
-
-TEST_F(ThreadCaptureTest, capture_kill) {
-  int ret = fork();
-
-  if (ret == 0) {
-    // child
-    sleep(10);
-  } else {
-    // parent
-    ASSERT_GT(ret, 0);
-
-    {
-      ScopedDisableMallocTimeout disable_malloc;
-
-      ThreadCapture thread_capture(ret, heap);
-      thread_capture.InjectTestFunc([&](pid_t tid) {
-        tgkill(ret, tid, SIGKILL);
-        usleep(10000);
-      });
-      auto list_tids = allocator::vector<pid_t>(heap);
-
-      ASSERT_TRUE(thread_capture.ListThreads(list_tids));
-      ASSERT_EQ(1U, list_tids.size());
-
-      ASSERT_FALSE(thread_capture.CaptureThreads());
-
-      if (!HasFailure()) {
-        ASSERT_FALSE(disable_malloc.timed_out());
-      }
-    }
-  }
-}
-
-TEST_F(ThreadCaptureTest, capture_signal) {
-  const int sig = SIGUSR1;
-
-  ScopedPipe pipe;
-
-  // For signal handler
-  static ScopedPipe* g_pipe;
-
-  Fork(
-      [&]() {
-        // child init
-        pipe.CloseReceiver();
-
-        g_pipe = &pipe;
-
-        struct sigaction act {};
-        act.sa_handler = [](int) {
-          char buf = '+';
-          write(g_pipe->Sender(), &buf, 1);
-          g_pipe->CloseSender();
-        };
-        sigaction(sig, &act, NULL);
-        sigset_t set;
-        sigemptyset(&set);
-        sigaddset(&set, sig);
-        pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-      },
-      [&]() {
-        // child cleanup
-        g_pipe = nullptr;
-        pipe.Close();
-      },
-      [&](pid_t child) {
-        // parent
-        ASSERT_GT(child, 0);
-        pipe.CloseSender();
-
-        {
-          ScopedDisableMallocTimeout disable_malloc;
-
-          ThreadCapture thread_capture(child, heap);
-          thread_capture.InjectTestFunc([&](pid_t tid) {
-            tgkill(child, tid, sig);
-            usleep(10000);
-          });
-          auto list_tids = allocator::vector<pid_t>(heap);
-
-          ASSERT_TRUE(thread_capture.ListThreads(list_tids));
-          ASSERT_EQ(1U, list_tids.size());
-
-          ASSERT_TRUE(thread_capture.CaptureThreads());
-
-          auto thread_info = allocator::vector<ThreadInfo>(heap);
-          ASSERT_TRUE(thread_capture.CapturedThreadInfo(thread_info));
-          ASSERT_EQ(1U, thread_info.size());
-          ASSERT_TRUE(thread_capture.ReleaseThreads());
-
-          usleep(100000);
-          char buf;
-          ASSERT_EQ(1, TEMP_FAILURE_RETRY(read(pipe.Receiver(), &buf, 1)));
-          ASSERT_EQ(buf, '+');
-
-          if (!HasFailure()) {
-            ASSERT_FALSE(disable_malloc.timed_out());
-          }
-        }
-      });
-}
-
-}  // namespace android
diff --git a/libmodprobe/Android.bp b/libmodprobe/Android.bp
new file mode 100644
index 0000000..78da46c
--- /dev/null
+++ b/libmodprobe/Android.bp
@@ -0,0 +1,31 @@
+cc_library_static {
+    name: "libmodprobe",
+    cflags: [
+        "-Werror",
+    ],
+    vendor_available: true,
+    recovery_available: true,
+    srcs: [
+        "libmodprobe.cpp",
+        "libmodprobe_ext.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+    ],
+    export_include_dirs: ["include/"],
+}
+
+cc_test {
+    name: "libmodprobe_tests",
+    cflags: ["-Werror"],
+    shared_libs: [
+        "libbase",
+    ],
+    local_include_dirs: ["include/"],
+    srcs: [
+        "libmodprobe_test.cpp",
+        "libmodprobe.cpp",
+        "libmodprobe_ext_test.cpp",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/libmodprobe/OWNERS b/libmodprobe/OWNERS
new file mode 100644
index 0000000..4b770b1
--- /dev/null
+++ b/libmodprobe/OWNERS
@@ -0,0 +1,2 @@
+tomcherry@google.com
+smuckle@google.com
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
new file mode 100644
index 0000000..ee6ae7a
--- /dev/null
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+class Modprobe {
+  public:
+    Modprobe(const std::vector<std::string>&);
+
+    bool LoadListedModules(bool strict = true);
+    bool LoadWithAliases(const std::string& module_name, bool strict,
+                         const std::string& parameters = "");
+    bool Remove(const std::string& module_name);
+    std::vector<std::string> ListModules(const std::string& pattern);
+    bool GetAllDependencies(const std::string& module, std::vector<std::string>* pre_dependencies,
+                            std::vector<std::string>* dependencies,
+                            std::vector<std::string>* post_dependencies);
+    void EnableBlacklist(bool enable);
+    void EnableVerbose(bool enable);
+
+  private:
+    std::string MakeCanonical(const std::string& module_path);
+    bool InsmodWithDeps(const std::string& module_name, const std::string& parameters);
+    bool Insmod(const std::string& path_name, const std::string& parameters);
+    bool Rmmod(const std::string& module_name);
+    std::vector<std::string> GetDependencies(const std::string& module);
+    bool ModuleExists(const std::string& module_name);
+    void AddOption(const std::string& module_name, const std::string& option_name,
+                   const std::string& value);
+    std::string GetKernelCmdline();
+
+    bool ParseDepCallback(const std::string& base_path, const std::vector<std::string>& args);
+    bool ParseAliasCallback(const std::vector<std::string>& args);
+    bool ParseSoftdepCallback(const std::vector<std::string>& args);
+    bool ParseLoadCallback(const std::vector<std::string>& args);
+    bool ParseOptionsCallback(const std::vector<std::string>& args);
+    bool ParseBlacklistCallback(const std::vector<std::string>& args);
+    void ParseKernelCmdlineOptions();
+    void ParseCfg(const std::string& cfg, std::function<bool(const std::vector<std::string>&)> f);
+
+    std::vector<std::pair<std::string, std::string>> module_aliases_;
+    std::unordered_map<std::string, std::vector<std::string>> module_deps_;
+    std::vector<std::pair<std::string, std::string>> module_pre_softdep_;
+    std::vector<std::pair<std::string, std::string>> module_post_softdep_;
+    std::vector<std::string> module_load_;
+    std::unordered_map<std::string, std::string> module_options_;
+    std::set<std::string> module_blacklist_;
+    std::unordered_set<std::string> module_loaded_;
+    bool blacklist_enabled = false;
+};
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
new file mode 100644
index 0000000..f22bbf1
--- /dev/null
+++ b/libmodprobe/libmodprobe.cpp
@@ -0,0 +1,508 @@
+/*
+ * 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.
+ */
+
+#include <modprobe/modprobe.h>
+
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+#include <algorithm>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+
+std::string Modprobe::MakeCanonical(const std::string& module_path) {
+    auto start = module_path.find_last_of('/');
+    if (start == std::string::npos) {
+        start = 0;
+    } else {
+        start += 1;
+    }
+    auto end = module_path.size();
+    if (android::base::EndsWith(module_path, ".ko")) {
+        end -= 3;
+    }
+    if ((end - start) <= 1) {
+        LOG(ERROR) << "malformed module name: " << module_path;
+        return "";
+    }
+    std::string module_name = module_path.substr(start, end - start);
+    // module names can have '-', but their file names will have '_'
+    std::replace(module_name.begin(), module_name.end(), '-', '_');
+    return module_name;
+}
+
+bool Modprobe::ParseDepCallback(const std::string& base_path,
+                                const std::vector<std::string>& args) {
+    std::vector<std::string> deps;
+    std::string prefix = "";
+
+    // Set first item as our modules path
+    std::string::size_type pos = args[0].find(':');
+    if (args[0][0] != '/') {
+        prefix = base_path + "/";
+    }
+    if (pos != std::string::npos) {
+        deps.emplace_back(prefix + args[0].substr(0, pos));
+    } else {
+        LOG(ERROR) << "dependency lines must start with name followed by ':'";
+    }
+
+    // Remaining items are dependencies of our module
+    for (auto arg = args.begin() + 1; arg != args.end(); ++arg) {
+        if ((*arg)[0] != '/') {
+            prefix = base_path + "/";
+        } else {
+            prefix = "";
+        }
+        deps.push_back(prefix + *arg);
+    }
+
+    std::string canonical_name = MakeCanonical(args[0].substr(0, pos));
+    if (canonical_name.empty()) {
+        return false;
+    }
+    this->module_deps_[canonical_name] = deps;
+
+    return true;
+}
+
+bool Modprobe::ParseAliasCallback(const std::vector<std::string>& args) {
+    auto it = args.begin();
+    const std::string& type = *it++;
+
+    if (type != "alias") {
+        LOG(ERROR) << "non-alias line encountered in modules.alias, found " << type;
+        return false;
+    }
+
+    if (args.size() != 3) {
+        LOG(ERROR) << "alias lines in modules.alias must have 3 entries, not " << args.size();
+        return false;
+    }
+
+    const std::string& alias = *it++;
+    const std::string& module_name = *it++;
+    this->module_aliases_.emplace_back(alias, module_name);
+
+    return true;
+}
+
+bool Modprobe::ParseSoftdepCallback(const std::vector<std::string>& args) {
+    auto it = args.begin();
+    const std::string& type = *it++;
+    std::string state = "";
+
+    if (type != "softdep") {
+        LOG(ERROR) << "non-softdep line encountered in modules.softdep, found " << type;
+        return false;
+    }
+
+    if (args.size() < 4) {
+        LOG(ERROR) << "softdep lines in modules.softdep must have at least 4 entries";
+        return false;
+    }
+
+    const std::string& module = *it++;
+    while (it != args.end()) {
+        const std::string& token = *it++;
+        if (token == "pre:" || token == "post:") {
+            state = token;
+            continue;
+        }
+        if (state == "") {
+            LOG(ERROR) << "malformed modules.softdep at token " << token;
+            return false;
+        }
+        if (state == "pre:") {
+            this->module_pre_softdep_.emplace_back(module, token);
+        } else {
+            this->module_post_softdep_.emplace_back(module, token);
+        }
+    }
+
+    return true;
+}
+
+bool Modprobe::ParseLoadCallback(const std::vector<std::string>& args) {
+    auto it = args.begin();
+    const std::string& module = *it++;
+
+    const std::string& canonical_name = MakeCanonical(module);
+    if (canonical_name.empty()) {
+        return false;
+    }
+    this->module_load_.emplace_back(canonical_name);
+
+    return true;
+}
+
+bool Modprobe::ParseOptionsCallback(const std::vector<std::string>& args) {
+    auto it = args.begin();
+    const std::string& type = *it++;
+
+    if (type != "options") {
+        LOG(ERROR) << "non-options line encountered in modules.options";
+        return false;
+    }
+
+    if (args.size() < 2) {
+        LOG(ERROR) << "lines in modules.options must have at least 2 entries, not " << args.size();
+        return false;
+    }
+
+    const std::string& module = *it++;
+    std::string options = "";
+
+    const std::string& canonical_name = MakeCanonical(module);
+    if (canonical_name.empty()) {
+        return false;
+    }
+
+    while (it != args.end()) {
+        options += *it++;
+        if (it != args.end()) {
+            options += " ";
+        }
+    }
+
+    auto [unused, inserted] = this->module_options_.emplace(canonical_name, options);
+    if (!inserted) {
+        LOG(ERROR) << "multiple options lines present for module " << module;
+        return false;
+    }
+    return true;
+}
+
+bool Modprobe::ParseBlacklistCallback(const std::vector<std::string>& args) {
+    auto it = args.begin();
+    const std::string& type = *it++;
+
+    if (type != "blacklist") {
+        LOG(ERROR) << "non-blacklist line encountered in modules.blacklist";
+        return false;
+    }
+
+    if (args.size() != 2) {
+        LOG(ERROR) << "lines in modules.blacklist must have exactly 2 entries, not " << args.size();
+        return false;
+    }
+
+    const std::string& module = *it++;
+
+    const std::string& canonical_name = MakeCanonical(module);
+    if (canonical_name.empty()) {
+        return false;
+    }
+    this->module_blacklist_.emplace(canonical_name);
+
+    return true;
+}
+
+void Modprobe::ParseCfg(const std::string& cfg,
+                        std::function<bool(const std::vector<std::string>&)> f) {
+    std::string cfg_contents;
+    if (!android::base::ReadFileToString(cfg, &cfg_contents, false)) {
+        return;
+    }
+
+    std::vector<std::string> lines = android::base::Split(cfg_contents, "\n");
+    for (const std::string line : lines) {
+        if (line.empty() || line[0] == '#') {
+            continue;
+        }
+        const std::vector<std::string> args = android::base::Split(line, " ");
+        if (args.empty()) continue;
+        f(args);
+    }
+    return;
+}
+
+void Modprobe::AddOption(const std::string& module_name, const std::string& option_name,
+                         const std::string& value) {
+    auto canonical_name = MakeCanonical(module_name);
+    auto options_iter = module_options_.find(canonical_name);
+    auto option_str = option_name + "=" + value;
+    if (options_iter != module_options_.end()) {
+        options_iter->second = options_iter->second + " " + option_str;
+    } else {
+        module_options_.emplace(canonical_name, option_str);
+    }
+}
+
+void Modprobe::ParseKernelCmdlineOptions(void) {
+    std::string cmdline = GetKernelCmdline();
+    std::string module_name = "";
+    std::string option_name = "";
+    std::string value = "";
+    bool in_module = true;
+    bool in_option = false;
+    bool in_value = false;
+    bool in_quotes = false;
+    int start = 0;
+
+    for (int i = 0; i < cmdline.size(); i++) {
+        if (cmdline[i] == '"') {
+            in_quotes = !in_quotes;
+        }
+
+        if (in_quotes) continue;
+
+        if (cmdline[i] == ' ') {
+            if (in_value) {
+                value = cmdline.substr(start, i - start);
+                if (!module_name.empty() && !option_name.empty()) {
+                    AddOption(module_name, option_name, value);
+                }
+            }
+            module_name = "";
+            option_name = "";
+            value = "";
+            in_value = false;
+            start = i + 1;
+            in_module = true;
+            continue;
+        }
+
+        if (cmdline[i] == '.') {
+            if (in_module) {
+                module_name = cmdline.substr(start, i - start);
+                start = i + 1;
+                in_module = false;
+            }
+            in_option = true;
+            continue;
+        }
+
+        if (cmdline[i] == '=') {
+            if (in_option) {
+                option_name = cmdline.substr(start, i - start);
+                start = i + 1;
+                in_option = false;
+            }
+            in_value = true;
+            continue;
+        }
+    }
+    if (in_value && !in_quotes) {
+        value = cmdline.substr(start, cmdline.size() - start);
+        if (!module_name.empty() && !option_name.empty()) {
+            AddOption(module_name, option_name, value);
+        }
+    }
+}
+
+Modprobe::Modprobe(const std::vector<std::string>& base_paths) {
+    using namespace std::placeholders;
+
+    for (const auto& base_path : base_paths) {
+        auto alias_callback = std::bind(&Modprobe::ParseAliasCallback, this, _1);
+        ParseCfg(base_path + "/modules.alias", alias_callback);
+
+        auto dep_callback = std::bind(&Modprobe::ParseDepCallback, this, base_path, _1);
+        ParseCfg(base_path + "/modules.dep", dep_callback);
+
+        auto softdep_callback = std::bind(&Modprobe::ParseSoftdepCallback, this, _1);
+        ParseCfg(base_path + "/modules.softdep", softdep_callback);
+
+        auto load_callback = std::bind(&Modprobe::ParseLoadCallback, this, _1);
+        ParseCfg(base_path + "/modules.load", load_callback);
+
+        auto options_callback = std::bind(&Modprobe::ParseOptionsCallback, this, _1);
+        ParseCfg(base_path + "/modules.options", options_callback);
+
+        auto blacklist_callback = std::bind(&Modprobe::ParseBlacklistCallback, this, _1);
+        ParseCfg(base_path + "/modules.blacklist", blacklist_callback);
+    }
+
+    ParseKernelCmdlineOptions();
+    android::base::SetMinimumLogSeverity(android::base::INFO);
+}
+
+void Modprobe::EnableBlacklist(bool enable) {
+    blacklist_enabled = enable;
+}
+
+void Modprobe::EnableVerbose(bool enable) {
+    if (enable) {
+        android::base::SetMinimumLogSeverity(android::base::VERBOSE);
+    } else {
+        android::base::SetMinimumLogSeverity(android::base::INFO);
+    }
+}
+
+std::vector<std::string> Modprobe::GetDependencies(const std::string& module) {
+    auto it = module_deps_.find(module);
+    if (it == module_deps_.end()) {
+        return {};
+    }
+    return it->second;
+}
+
+bool Modprobe::InsmodWithDeps(const std::string& module_name, const std::string& parameters) {
+    if (module_name.empty()) {
+        LOG(ERROR) << "Need valid module name, given: " << module_name;
+        return false;
+    }
+
+    auto dependencies = GetDependencies(module_name);
+    if (dependencies.empty()) {
+        LOG(ERROR) << "Module " << module_name << " not in dependency file";
+        return false;
+    }
+
+    // load module dependencies in reverse order
+    for (auto dep = dependencies.rbegin(); dep != dependencies.rend() - 1; ++dep) {
+        LOG(VERBOSE) << "Loading hard dep for '" << module_name << "': " << *dep;
+        if (!LoadWithAliases(*dep, true)) {
+            return false;
+        }
+    }
+
+    // try to load soft pre-dependencies
+    for (const auto& [module, softdep] : module_pre_softdep_) {
+        if (module_name == module) {
+            LOG(VERBOSE) << "Loading soft pre-dep for '" << module << "': " << softdep;
+            LoadWithAliases(softdep, false);
+        }
+    }
+
+    // load target module itself with args
+    if (!Insmod(dependencies[0], parameters)) {
+        return false;
+    }
+
+    // try to load soft post-dependencies
+    for (const auto& [module, softdep] : module_post_softdep_) {
+        if (module_name == module) {
+            LOG(VERBOSE) << "Loading soft post-dep for '" << module << "': " << softdep;
+            LoadWithAliases(softdep, false);
+        }
+    }
+
+    return true;
+}
+
+bool Modprobe::LoadWithAliases(const std::string& module_name, bool strict,
+                               const std::string& parameters) {
+    auto canonical_name = MakeCanonical(module_name);
+    if (module_loaded_.count(canonical_name)) {
+        return true;
+    }
+
+    std::set<std::string> modules_to_load = {canonical_name};
+    bool module_loaded = false;
+
+    // use aliases to expand list of modules to load (multiple modules
+    // may alias themselves to the requested name)
+    for (const auto& [alias, aliased_module] : module_aliases_) {
+        if (fnmatch(alias.c_str(), module_name.c_str(), 0) != 0) continue;
+        LOG(VERBOSE) << "Found alias for '" << module_name << "': '" << aliased_module;
+        if (module_loaded_.count(MakeCanonical(aliased_module))) continue;
+        modules_to_load.emplace(aliased_module);
+    }
+
+    // attempt to load all modules aliased to this name
+    for (const auto& module : modules_to_load) {
+        if (!ModuleExists(module)) continue;
+        if (InsmodWithDeps(module, parameters)) module_loaded = true;
+    }
+
+    if (strict && !module_loaded) {
+        LOG(ERROR) << "LoadWithAliases was unable to load " << module_name;
+        return false;
+    }
+    return true;
+}
+
+bool Modprobe::LoadListedModules(bool strict) {
+    auto ret = true;
+    for (const auto& module : module_load_) {
+        if (!LoadWithAliases(module, true)) {
+            ret = false;
+            if (strict) break;
+        }
+    }
+    return ret;
+}
+
+bool Modprobe::Remove(const std::string& module_name) {
+    auto dependencies = GetDependencies(MakeCanonical(module_name));
+    if (dependencies.empty()) {
+        LOG(ERROR) << "Empty dependencies for module " << module_name;
+        return false;
+    }
+    if (!Rmmod(dependencies[0])) {
+        return false;
+    }
+    for (auto dep = dependencies.begin() + 1; dep != dependencies.end(); ++dep) {
+        Rmmod(*dep);
+    }
+    return true;
+}
+
+std::vector<std::string> Modprobe::ListModules(const std::string& pattern) {
+    std::vector<std::string> rv;
+    for (const auto& [module, deps] : module_deps_) {
+        // Attempt to match both the canonical module name and the module filename.
+        if (!fnmatch(pattern.c_str(), module.c_str(), 0)) {
+            rv.emplace_back(module);
+        } else if (!fnmatch(pattern.c_str(), basename(deps[0].c_str()), 0)) {
+            rv.emplace_back(deps[0]);
+        }
+    }
+    return rv;
+}
+
+bool Modprobe::GetAllDependencies(const std::string& module,
+                                  std::vector<std::string>* pre_dependencies,
+                                  std::vector<std::string>* dependencies,
+                                  std::vector<std::string>* post_dependencies) {
+    std::string canonical_name = MakeCanonical(module);
+    if (pre_dependencies) {
+        pre_dependencies->clear();
+        for (const auto& [it_module, it_softdep] : module_pre_softdep_) {
+            if (canonical_name == it_module) {
+                pre_dependencies->emplace_back(it_softdep);
+            }
+        }
+    }
+    if (dependencies) {
+        dependencies->clear();
+        auto hard_deps = GetDependencies(canonical_name);
+        if (hard_deps.empty()) {
+            return false;
+        }
+        for (auto dep = hard_deps.rbegin(); dep != hard_deps.rend(); dep++) {
+            dependencies->emplace_back(*dep);
+        }
+    }
+    if (post_dependencies) {
+        for (const auto& [it_module, it_softdep] : module_post_softdep_) {
+            if (canonical_name == it_module) {
+                post_dependencies->emplace_back(it_softdep);
+            }
+        }
+    }
+    return true;
+}
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
new file mode 100644
index 0000000..99472c1
--- /dev/null
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#include <sys/stat.h>
+#include <sys/syscall.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
+#include <modprobe/modprobe.h>
+
+std::string Modprobe::GetKernelCmdline(void) {
+    std::string cmdline;
+    if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
+        return "";
+    }
+    return cmdline;
+}
+
+bool Modprobe::Insmod(const std::string& path_name, const std::string& parameters) {
+    android::base::unique_fd fd(
+            TEMP_FAILURE_RETRY(open(path_name.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
+    if (fd == -1) {
+        LOG(ERROR) << "Could not open module '" << path_name << "'";
+        return false;
+    }
+
+    auto canonical_name = MakeCanonical(path_name);
+    std::string options = "";
+    auto options_iter = module_options_.find(canonical_name);
+    if (options_iter != module_options_.end()) {
+        options = options_iter->second;
+    }
+    if (!parameters.empty()) {
+        options = options + " " + parameters;
+    }
+
+    LOG(INFO) << "Loading module " << path_name << " with args \"" << options << "\"";
+    int ret = syscall(__NR_finit_module, fd.get(), options.c_str(), 0);
+    if (ret != 0) {
+        if (errno == EEXIST) {
+            // Module already loaded
+            module_loaded_.emplace(canonical_name);
+            return true;
+        }
+        LOG(ERROR) << "Failed to insmod '" << path_name << "' with args '" << options << "'";
+        return false;
+    }
+
+    LOG(INFO) << "Loaded kernel module " << path_name;
+    module_loaded_.emplace(canonical_name);
+    return true;
+}
+
+bool Modprobe::Rmmod(const std::string& module_name) {
+    auto canonical_name = MakeCanonical(module_name);
+    int ret = syscall(__NR_delete_module, canonical_name.c_str(), O_NONBLOCK);
+    if (ret != 0) {
+        PLOG(ERROR) << "Failed to remove module '" << module_name << "'";
+        return false;
+    }
+    module_loaded_.erase(canonical_name);
+    return true;
+}
+
+bool Modprobe::ModuleExists(const std::string& module_name) {
+    struct stat fileStat;
+    if (blacklist_enabled && module_blacklist_.count(module_name)) {
+        LOG(INFO) << "module " << module_name << " is blacklisted";
+        return false;
+    }
+    auto deps = GetDependencies(module_name);
+    if (deps.empty()) {
+        // missing deps can happen in the case of an alias
+        return false;
+    }
+    if (stat(deps.front().c_str(), &fileStat)) {
+        LOG(INFO) << "module " << module_name << " does not exist";
+        return false;
+    }
+    if (!S_ISREG(fileStat.st_mode)) {
+        LOG(INFO) << "module " << module_name << " is not a regular file";
+        return false;
+    }
+    return true;
+}
diff --git a/libmodprobe/libmodprobe_ext_test.cpp b/libmodprobe/libmodprobe_ext_test.cpp
new file mode 100644
index 0000000..057dea3
--- /dev/null
+++ b/libmodprobe/libmodprobe_ext_test.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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 <sys/stat.h>
+#include <sys/syscall.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+
+#include <modprobe/modprobe.h>
+
+#include "libmodprobe_test.h"
+
+std::string Modprobe::GetKernelCmdline(void) {
+    return kernel_cmdline;
+}
+
+bool Modprobe::Insmod(const std::string& path_name, const std::string& parameters) {
+    auto deps = GetDependencies(MakeCanonical(path_name));
+    if (deps.empty()) {
+        return false;
+    }
+    if (std::find(test_modules.begin(), test_modules.end(), deps.front()) == test_modules.end()) {
+        return false;
+    }
+    for (auto it = modules_loaded.begin(); it != modules_loaded.end(); ++it) {
+        if (android::base::StartsWith(*it, path_name)) {
+            return true;
+        }
+    }
+    std::string options;
+    auto options_iter = module_options_.find(MakeCanonical(path_name));
+    if (options_iter != module_options_.end()) {
+        options = " " + options_iter->second;
+    }
+    if (!parameters.empty()) {
+        options = options + " " + parameters;
+    }
+
+    modules_loaded.emplace_back(path_name + options);
+    return true;
+}
+
+bool Modprobe::Rmmod(const std::string& module_name) {
+    for (auto it = modules_loaded.begin(); it != modules_loaded.end(); it++) {
+        if (*it == module_name || android::base::StartsWith(*it, module_name + " ")) {
+            modules_loaded.erase(it);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool Modprobe::ModuleExists(const std::string& module_name) {
+    auto deps = GetDependencies(module_name);
+    if (blacklist_enabled && module_blacklist_.count(module_name)) {
+        return false;
+    }
+    if (deps.empty()) {
+        // missing deps can happen in the case of an alias
+        return false;
+    }
+    return std::find(test_modules.begin(), test_modules.end(), deps.front()) != test_modules.end();
+}
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
new file mode 100644
index 0000000..879c7f2
--- /dev/null
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -0,0 +1,180 @@
+/*
+ * 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 <functional>
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+
+#include <modprobe/modprobe.h>
+
+#include "libmodprobe_test.h"
+
+// Used by libmodprobe_ext_test to check if requested modules are present.
+std::vector<std::string> test_modules;
+
+// Used by libmodprobe_ext_test to report which modules would have been loaded.
+std::vector<std::string> modules_loaded;
+
+// Used by libmodprobe_ext_test to fake a kernel commandline
+std::string kernel_cmdline;
+
+TEST(libmodprobe, Test) {
+    kernel_cmdline =
+            "flag1 flag2 test1.option1=50 test4.option3=\"set x\" test1.option2=60 "
+            "test8. test5.option1= test10.option1=1";
+    test_modules = {
+            "/test1.ko",  "/test2.ko",  "/test3.ko",  "/test4.ko",  "/test5.ko",
+            "/test6.ko",  "/test7.ko",  "/test8.ko",  "/test9.ko",  "/test10.ko",
+            "/test11.ko", "/test12.ko", "/test13.ko", "/test14.ko", "/test15.ko",
+    };
+
+    std::vector<std::string> expected_modules_loaded = {
+            "/test14.ko",
+            "/test15.ko",
+            "/test3.ko",
+            "/test4.ko option3=\"set x\"",
+            "/test1.ko option1=50 option2=60",
+            "/test6.ko",
+            "/test2.ko",
+            "/test5.ko option1=",
+            "/test8.ko",
+            "/test7.ko param1=4",
+            "/test9.ko param_x=1 param_y=2 param_z=3",
+            "/test10.ko option1=1",
+            "/test12.ko",
+            "/test11.ko",
+            "/test13.ko",
+    };
+
+    std::vector<std::string> expected_after_remove = {
+            "/test14.ko",
+            "/test15.ko",
+            "/test1.ko option1=50 option2=60",
+            "/test6.ko",
+            "/test2.ko",
+            "/test5.ko option1=",
+            "/test8.ko",
+            "/test7.ko param1=4",
+            "/test9.ko param_x=1 param_y=2 param_z=3",
+            "/test10.ko option1=1",
+            "/test12.ko",
+            "/test11.ko",
+            "/test13.ko",
+    };
+
+    const std::string modules_dep =
+            "test1.ko:\n"
+            "test2.ko:\n"
+            "test3.ko:\n"
+            "test4.ko: test3.ko\n"
+            "test5.ko: test2.ko test6.ko\n"
+            "test6.ko:\n"
+            "test7.ko:\n"
+            "test8.ko:\n"
+            "test9.ko:\n"
+            "test10.ko:\n"
+            "test11.ko:\n"
+            "test12.ko:\n"
+            "test13.ko:\n"
+            "test14.ko:\n"
+            "test15.ko:\n";
+
+    const std::string modules_softdep =
+            "softdep test7 pre: test8\n"
+            "softdep test9 post: test10\n"
+            "softdep test11 pre: test12 post: test13\n"
+            "softdep test3 pre: test141516\n";
+
+    const std::string modules_alias =
+            "# Aliases extracted from modules themselves.\n"
+            "\n"
+            "alias test141516 test14\n"
+            "alias test141516 test15\n"
+            "alias test141516 test16\n";
+
+    const std::string modules_options =
+            "options test7.ko param1=4\n"
+            "options test9.ko param_x=1 param_y=2 param_z=3\n"
+            "options test100.ko param_1=1\n";
+
+    const std::string modules_blacklist =
+            "blacklist test9.ko\n"
+            "blacklist test3.ko\n";
+
+    const std::string modules_load =
+            "test4.ko\n"
+            "test1.ko\n"
+            "test3.ko\n"
+            "test5.ko\n"
+            "test7.ko\n"
+            "test9.ko\n"
+            "test11.ko\n";
+
+    TemporaryDir dir;
+    auto dir_path = std::string(dir.path);
+    ASSERT_TRUE(android::base::WriteStringToFile(modules_alias, dir_path + "/modules.alias", 0600,
+                                                 getuid(), getgid()));
+
+    ASSERT_TRUE(android::base::WriteStringToFile(modules_dep, dir_path + "/modules.dep", 0600,
+                                                 getuid(), getgid()));
+    ASSERT_TRUE(android::base::WriteStringToFile(modules_softdep, dir_path + "/modules.softdep",
+                                                 0600, getuid(), getgid()));
+    ASSERT_TRUE(android::base::WriteStringToFile(modules_options, dir_path + "/modules.options",
+                                                 0600, getuid(), getgid()));
+    ASSERT_TRUE(android::base::WriteStringToFile(modules_load, dir_path + "/modules.load", 0600,
+                                                 getuid(), getgid()));
+    ASSERT_TRUE(android::base::WriteStringToFile(modules_blacklist, dir_path + "/modules.blacklist",
+                                                 0600, getuid(), getgid()));
+
+    for (auto i = test_modules.begin(); i != test_modules.end(); ++i) {
+        *i = dir.path + *i;
+    }
+
+    Modprobe m({dir.path});
+    EXPECT_TRUE(m.LoadListedModules());
+
+    GTEST_LOG_(INFO) << "Expected modules loaded (in order):";
+    for (auto i = expected_modules_loaded.begin(); i != expected_modules_loaded.end(); ++i) {
+        *i = dir.path + *i;
+        GTEST_LOG_(INFO) << "\"" << *i << "\"";
+    }
+    GTEST_LOG_(INFO) << "Actual modules loaded (in order):";
+    for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) {
+        GTEST_LOG_(INFO) << "\"" << *i << "\"";
+    }
+
+    EXPECT_TRUE(modules_loaded == expected_modules_loaded);
+
+    EXPECT_TRUE(m.Remove("test4"));
+
+    GTEST_LOG_(INFO) << "Expected modules loaded after removing test4 (in order):";
+    for (auto i = expected_after_remove.begin(); i != expected_after_remove.end(); ++i) {
+        *i = dir.path + *i;
+        GTEST_LOG_(INFO) << "\"" << *i << "\"";
+    }
+    GTEST_LOG_(INFO) << "Actual modules loaded after removing test4 (in order):";
+    for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) {
+        GTEST_LOG_(INFO) << "\"" << *i << "\"";
+    }
+
+    EXPECT_TRUE(modules_loaded == expected_after_remove);
+
+    m.EnableBlacklist(true);
+    EXPECT_FALSE(m.LoadWithAliases("test4", true));
+}
diff --git a/adb/daemon/reboot_service.h b/libmodprobe/libmodprobe_test.h
similarity index 74%
rename from adb/daemon/reboot_service.h
rename to libmodprobe/libmodprobe_test.h
index f68913e..e7b949f 100644
--- a/adb/daemon/reboot_service.h
+++ b/libmodprobe/libmodprobe_test.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -17,9 +17,8 @@
 #pragma once
 
 #include <string>
+#include <vector>
 
-#include "adb_unique_fd.h"
-
-#if defined(__ANDROID__)
-void reboot_service(unique_fd fd, const std::string& arg);
-#endif
+extern std::string kernel_cmdline;
+extern std::vector<std::string> test_modules;
+extern std::vector<std::string> modules_loaded;
diff --git a/libnativebridge/.clang-format b/libnativebridge/.clang-format
deleted file mode 120000
index fd0645f..0000000
--- a/libnativebridge/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-../.clang-format-2
\ No newline at end of file
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
deleted file mode 100644
index 10d42e4..0000000
--- a/libnativebridge/Android.bp
+++ /dev/null
@@ -1,61 +0,0 @@
-cc_defaults {
-    name: "libnativebridge-defaults",
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=protected",
-    ],
-    header_libs: ["libnativebridge-headers"],
-    export_header_lib_headers: ["libnativebridge-headers"],
-}
-
-cc_library_headers {
-    name: "libnativebridge-headers",
-
-    host_supported: true,
-    export_include_dirs: ["include"],
-}
-
-cc_library {
-    name: "libnativebridge",
-    defaults: ["libnativebridge-defaults"],
-
-    host_supported: true,
-    srcs: ["native_bridge.cc"],
-    header_libs: [
-        "libbase_headers",
-    ],
-    shared_libs: [
-        "liblog",
-    ],
-    // TODO(jiyong): remove this line after aosp/885921 lands
-    export_include_dirs: ["include"],
-
-    target: {
-        android: {
-            version_script: "libnativebridge.map.txt",
-        },
-        linux: {
-            version_script: "libnativebridge.map.txt",
-        },
-    },
-
-    stubs: {
-        symbol_file: "libnativebridge.map.txt",
-        versions: ["1"],
-    },
-}
-
-// TODO(b/124250621): eliminate the need for this library
-cc_library {
-    name: "libnativebridge_lazy",
-    defaults: ["libnativebridge-defaults"],
-
-    host_supported: false,
-    srcs: ["native_bridge_lazy.cc"],
-    required: ["libnativebridge"],
-}
-
-subdirs = ["tests"]
diff --git a/libnativebridge/OWNERS b/libnativebridge/OWNERS
deleted file mode 100644
index daf87f4..0000000
--- a/libnativebridge/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-dimitry@google.com
-eaeltsin@google.com
-ngeoffray@google.com
-oth@google.com
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
deleted file mode 100644
index e9c9500..0000000
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2014 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 NATIVE_BRIDGE_H_
-#define NATIVE_BRIDGE_H_
-
-#include <signal.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "jni.h"
-
-#ifdef __cplusplus
-namespace android {
-extern "C" {
-#endif  // __cplusplus
-
-struct NativeBridgeRuntimeCallbacks;
-struct NativeBridgeRuntimeValues;
-
-// Function pointer type for sigaction. This is mostly the signature of a signal handler, except
-// for the return type. The runtime needs to know whether the signal was handled or should be given
-// to the chain.
-typedef bool (*NativeBridgeSignalHandlerFn)(int, siginfo_t*, void*);
-
-// Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
-// signals that we do not want to load a native bridge.
-bool LoadNativeBridge(const char* native_bridge_library_filename,
-                      const struct NativeBridgeRuntimeCallbacks* runtime_callbacks);
-
-// Quick check whether a native bridge will be needed. This is based off of the instruction set
-// of the process.
-bool NeedsNativeBridge(const char* instruction_set);
-
-// Do the early initialization part of the native bridge, if necessary. This should be done under
-// high privileges.
-bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set);
-
-// Initialize the native bridge, if any. Should be called by Runtime::DidForkFromZygote. The JNIEnv*
-// will be used to modify the app environment for the bridge.
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set);
-
-// Unload the native bridge, if any. Should be called by Runtime::DidForkFromZygote.
-void UnloadNativeBridge();
-
-// Check whether a native bridge is available (opened or initialized). Requires a prior call to
-// LoadNativeBridge.
-bool NativeBridgeAvailable();
-
-// Check whether a native bridge is available (initialized). Requires a prior call to
-// LoadNativeBridge & InitializeNativeBridge.
-bool NativeBridgeInitialized();
-
-// Load a shared library that is supported by the native bridge.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeLoadLibraryExt() instead in namespace scenario.
-void* NativeBridgeLoadLibrary(const char* libpath, int flag);
-
-// Get a native bridge trampoline for specified native method.
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len);
-
-// True if native library paths are valid and is for an ABI that is supported by native bridge.
-// The *libpath* must point to a library.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeIsPathSupported() instead in namespace scenario.
-bool NativeBridgeIsSupported(const char* libpath);
-
-// Returns the version number of the native bridge. This information is available after a
-// successful LoadNativeBridge() and before closing it, that is, as long as NativeBridgeAvailable()
-// returns true. Returns 0 otherwise.
-uint32_t NativeBridgeGetVersion();
-
-// Returns a signal handler that the bridge would like to be managed. Only valid for a native
-// bridge supporting the version 2 interface. Will return null if the bridge does not support
-// version 2, or if it doesn't have a signal handler it wants to be known.
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal);
-
-// Returns whether we have seen a native bridge error. This could happen because the library
-// was not found, rejected, could not be initialized and so on.
-//
-// This functionality is mainly for testing.
-bool NativeBridgeError();
-
-// Returns whether a given string is acceptable as a native bridge library filename.
-//
-// This functionality is exposed mainly for testing.
-bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename);
-
-// Decrements the reference count on the dynamic library handler. If the reference count drops
-// to zero then the dynamic library is unloaded. Returns 0 on success and non-zero on error.
-int NativeBridgeUnloadLibrary(void* handle);
-
-// Get last error message of native bridge when fail to load library or search symbol.
-// This is reflection of dlerror() for native bridge.
-const char* NativeBridgeGetError();
-
-struct native_bridge_namespace_t;
-
-// True if native library paths are valid and is for an ABI that is supported by native bridge.
-// Different from NativeBridgeIsSupported(), the *path* here must be a directory containing
-// libraries of an ABI.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeIsSupported() instead in non-namespace scenario.
-bool NativeBridgeIsPathSupported(const char* path);
-
-// Initializes anonymous namespace.
-// NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
-//
-// The anonymous namespace is used in the case when a NativeBridge implementation
-// cannot identify the caller of dlopen/dlsym which happens for the code not loaded
-// by dynamic linker; for example calls from the mono-compiled code.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Should not use in non-namespace scenario.
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
-                                        const char* anon_ns_library_path);
-
-// Create new namespace in which native libraries will be loaded.
-// NativeBridge's peer of android_create_namespace() of dynamic linker.
-//
-// The libraries in the namespace are searched by folowing order:
-// 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
-// 2. In directories specified by DT_RUNPATH of the "needed by" binary.
-// 3. deault_library_path (This of this as namespace-local default library path)
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Should not use in non-namespace scenario.
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
-    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
-    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns);
-
-// Creates a link which shares some libraries from one namespace to another.
-// NativeBridge's peer of android_link_namespaces() of dynamic linker.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Should not use in non-namespace scenario.
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
-                                struct native_bridge_namespace_t* to,
-                                const char* shared_libs_sonames);
-
-// Load a shared library with namespace key that is supported by the native bridge.
-// NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
-// extension.
-//
-// Starting with v3, NativeBridge has two scenarios: with/without namespace.
-// Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
-                                 struct native_bridge_namespace_t* ns);
-
-// Returns exported namespace by the name. This is a reflection of
-// android_get_exported_namespace function. Introduced in v5.
-struct native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name);
-
-// Native bridge interfaces to runtime.
-struct NativeBridgeCallbacks {
-  // Version number of the interface.
-  uint32_t version;
-
-  // Initialize native bridge. Native bridge's internal implementation must ensure MT safety and
-  // that the native bridge is initialized only once. Thus it is OK to call this interface for an
-  // already initialized native bridge.
-  //
-  // Parameters:
-  //   runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
-  // Returns:
-  //   true if initialization was successful.
-  bool (*initialize)(const struct NativeBridgeRuntimeCallbacks* runtime_cbs,
-                     const char* private_dir, const char* instruction_set);
-
-  // Load a shared library that is supported by the native bridge.
-  //
-  // Parameters:
-  //   libpath [IN] path to the shared library
-  //   flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
-  // Returns:
-  //   The opaque handle of the shared library if sucessful, otherwise NULL
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Use loadLibraryExt instead in namespace scenario.
-  void* (*loadLibrary)(const char* libpath, int flag);
-
-  // Get a native bridge trampoline for specified native method. The trampoline has same
-  // sigature as the native method.
-  //
-  // Parameters:
-  //   handle [IN] the handle returned from loadLibrary
-  //   shorty [IN] short descriptor of native method
-  //   len [IN] length of shorty
-  // Returns:
-  //   address of trampoline if successful, otherwise NULL
-  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
-
-  // Check whether native library is valid and is for an ABI that is supported by native bridge.
-  //
-  // Parameters:
-  //   libpath [IN] path to the shared library
-  // Returns:
-  //   TRUE if library is supported by native bridge, FALSE otherwise
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Use isPathSupported instead in namespace scenario.
-  bool (*isSupported)(const char* libpath);
-
-  // Provide environment values required by the app running with native bridge according to the
-  // instruction set.
-  //
-  // Parameters:
-  //   instruction_set [IN] the instruction set of the app
-  // Returns:
-  //   NULL if not supported by native bridge.
-  //   Otherwise, return all environment values to be set after fork.
-  const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);
-
-  // Added callbacks in version 2.
-
-  // Check whether the bridge is compatible with the given version. A bridge may decide not to be
-  // forwards- or backwards-compatible, and libnativebridge will then stop using it.
-  //
-  // Parameters:
-  //   bridge_version [IN] the version of libnativebridge.
-  // Returns:
-  //   true if the native bridge supports the given version of libnativebridge.
-  bool (*isCompatibleWith)(uint32_t bridge_version);
-
-  // A callback to retrieve a native bridge's signal handler for the specified signal. The runtime
-  // will ensure that the signal handler is being called after the runtime's own handler, but before
-  // all chained handlers. The native bridge should not try to install the handler by itself, as
-  // that will potentially lead to cycles.
-  //
-  // Parameters:
-  //   signal [IN] the signal for which the handler is asked for. Currently, only SIGSEGV is
-  //                 supported by the runtime.
-  // Returns:
-  //   NULL if the native bridge doesn't use a handler or doesn't want it to be managed by the
-  //   runtime.
-  //   Otherwise, a pointer to the signal handler.
-  NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal);
-
-  // Added callbacks in version 3.
-
-  // Decrements the reference count on the dynamic library handler. If the reference count drops
-  // to zero then the dynamic library is unloaded.
-  //
-  // Parameters:
-  //   handle [IN] the handler of a dynamic library.
-  //
-  // Returns:
-  //   0 on success, and nonzero on error.
-  int (*unloadLibrary)(void* handle);
-
-  // Dump the last failure message of native bridge when fail to load library or search symbol.
-  //
-  // Parameters:
-  //
-  // Returns:
-  //   A string describing the most recent error that occurred when load library
-  //   or lookup symbol via native bridge.
-  const char* (*getError)();
-
-  // Check whether library paths are supported by native bridge.
-  //
-  // Parameters:
-  //   library_path [IN] search paths for native libraries (directories separated by ':')
-  // Returns:
-  //   TRUE if libraries within search paths are supported by native bridge, FALSE otherwise
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Use isSupported instead in non-namespace scenario.
-  bool (*isPathSupported)(const char* library_path);
-
-  // Initializes anonymous namespace at native bridge side.
-  // NativeBridge's peer of android_init_anonymous_namespace() of dynamic linker.
-  //
-  // The anonymous namespace is used in the case when a NativeBridge implementation
-  // cannot identify the caller of dlopen/dlsym which happens for the code not loaded
-  // by dynamic linker; for example calls from the mono-compiled code.
-  //
-  // Parameters:
-  //   public_ns_sonames [IN] the name of "public" libraries.
-  //   anon_ns_library_path [IN] the library search path of (anonymous) namespace.
-  // Returns:
-  //   true if the pass is ok.
-  //   Otherwise, false.
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Should not use in non-namespace scenario.
-  bool (*initAnonymousNamespace)(const char* public_ns_sonames, const char* anon_ns_library_path);
-
-  // Create new namespace in which native libraries will be loaded.
-  // NativeBridge's peer of android_create_namespace() of dynamic linker.
-  //
-  // Parameters:
-  //   name [IN] the name of the namespace.
-  //   ld_library_path [IN] the first set of library search paths of the namespace.
-  //   default_library_path [IN] the second set of library search path of the namespace.
-  //   type [IN] the attribute of the namespace.
-  //   permitted_when_isolated_path [IN] the permitted path for isolated namespace(if it is).
-  //   parent_ns [IN] the pointer of the parent namespace to be inherited from.
-  // Returns:
-  //   native_bridge_namespace_t* for created namespace or nullptr in the case of error.
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Should not use in non-namespace scenario.
-  struct native_bridge_namespace_t* (*createNamespace)(const char* name,
-                                                       const char* ld_library_path,
-                                                       const char* default_library_path,
-                                                       uint64_t type,
-                                                       const char* permitted_when_isolated_path,
-                                                       struct native_bridge_namespace_t* parent_ns);
-
-  // Creates a link which shares some libraries from one namespace to another.
-  // NativeBridge's peer of android_link_namespaces() of dynamic linker.
-  //
-  // Parameters:
-  //   from [IN] the namespace where libraries are accessed.
-  //   to [IN] the namespace where libraries are loaded.
-  //   shared_libs_sonames [IN] the libraries to be shared.
-  //
-  // Returns:
-  //   Whether successed or not.
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Should not use in non-namespace scenario.
-  bool (*linkNamespaces)(struct native_bridge_namespace_t* from,
-                         struct native_bridge_namespace_t* to, const char* shared_libs_sonames);
-
-  // Load a shared library within a namespace.
-  // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
-  // extension.
-  //
-  // Parameters:
-  //   libpath [IN] path to the shared library
-  //   flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
-  //   ns [IN] the pointer of the namespace in which the library should be loaded.
-  // Returns:
-  //   The opaque handle of the shared library if sucessful, otherwise NULL
-  //
-  // Starting with v3, NativeBridge has two scenarios: with/without namespace.
-  // Use loadLibrary instead in non-namespace scenario.
-  void* (*loadLibraryExt)(const char* libpath, int flag, struct native_bridge_namespace_t* ns);
-
-  // Get native bridge version of vendor namespace.
-  // The vendor namespace is the namespace used to load vendor public libraries.
-  // With O release this namespace can be different from the default namespace.
-  // For the devices without enable vendor namespaces this function should return null
-  //
-  // Returns:
-  //   vendor namespace or null if it was not set up for the device
-  //
-  // Starting with v5 (Android Q) this function is no longer used.
-  // Use getExportedNamespace() below.
-  struct native_bridge_namespace_t* (*getVendorNamespace)();
-
-  // Get native bridge version of exported namespace. Peer of
-  // android_get_exported_namespace(const char*) function.
-  //
-  // Returns:
-  //   exported namespace or null if it was not set up for the device
-  struct native_bridge_namespace_t* (*getExportedNamespace)(const char* name);
-};
-
-// Runtime interfaces to native bridge.
-struct NativeBridgeRuntimeCallbacks {
-  // Get shorty of a Java method. The shorty is supposed to be persistent in memory.
-  //
-  // Parameters:
-  //   env [IN] pointer to JNIenv.
-  //   mid [IN] Java methodID.
-  // Returns:
-  //   short descriptor for method.
-  const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
-
-  // Get number of native methods for specified class.
-  //
-  // Parameters:
-  //   env [IN] pointer to JNIenv.
-  //   clazz [IN] Java class object.
-  // Returns:
-  //   number of native methods.
-  uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
-
-  // Get at most 'method_count' native methods for specified class 'clazz'. Results are outputed
-  // via 'methods' [OUT]. The signature pointer in JNINativeMethod is reused as the method shorty.
-  //
-  // Parameters:
-  //   env [IN] pointer to JNIenv.
-  //   clazz [IN] Java class object.
-  //   methods [OUT] array of method with the name, shorty, and fnPtr.
-  //   method_count [IN] max number of elements in methods.
-  // Returns:
-  //   number of method it actually wrote to methods.
-  uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
-                               uint32_t method_count);
-};
-
-#ifdef __cplusplus
-}  // extern "C"
-}  // namespace android
-#endif  // __cplusplus
-
-#endif  // NATIVE_BRIDGE_H_
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
deleted file mode 100644
index a6841a3..0000000
--- a/libnativebridge/libnativebridge.map.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# 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.
-#
-
-# TODO(b/122710865): Most of these uses come from libnativeloader, which should be bundled
-# together with libnativebridge in the APEX. Once this happens, prune this list.
-LIBNATIVEBRIDGE_1 {
-  global:
-    NativeBridgeIsSupported;
-    NativeBridgeLoadLibrary;
-    NativeBridgeUnloadLibrary;
-    NativeBridgeGetError;
-    NativeBridgeIsPathSupported;
-    NativeBridgeCreateNamespace;
-    NativeBridgeGetExportedNamespace;
-    NativeBridgeLinkNamespaces;
-    NativeBridgeLoadLibraryExt;
-    NativeBridgeInitAnonymousNamespace;
-    NativeBridgeInitialized;
-    NativeBridgeGetTrampoline;
-    LoadNativeBridge;
-    PreInitializeNativeBridge;
-    InitializeNativeBridge;
-    NativeBridgeGetVersion;
-    NativeBridgeGetSignalHandler;
-    UnloadNativeBridge;
-    NativeBridgeAvailable;
-    NeedsNativeBridge;
-    NativeBridgeError;
-    NativeBridgeNameAcceptable;
-  local:
-    *;
-};
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
deleted file mode 100644
index 9adba9a..0000000
--- a/libnativebridge/native_bridge.cc
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Copyright (C) 2014 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 "nativebridge"
-
-#include "nativebridge/native_bridge.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <cstring>
-
-#include <android-base/macros.h>
-#include <log/log.h>
-
-namespace android {
-
-#ifdef __APPLE__
-template <typename T>
-void UNUSED(const T&) {}
-#endif
-
-extern "C" {
-
-// Environment values required by the apps running with native bridge.
-struct NativeBridgeRuntimeValues {
-    const char* os_arch;
-    const char* cpu_abi;
-    const char* cpu_abi2;
-    const char* *supported_abis;
-    int32_t abi_count;
-};
-
-// The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks.
-static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf";
-
-enum class NativeBridgeState {
-  kNotSetup,                        // Initial state.
-  kOpened,                          // After successful dlopen.
-  kPreInitialized,                  // After successful pre-initialization.
-  kInitialized,                     // After successful initialization.
-  kClosed                           // Closed or errors.
-};
-
-static constexpr const char* kNotSetupString = "kNotSetup";
-static constexpr const char* kOpenedString = "kOpened";
-static constexpr const char* kPreInitializedString = "kPreInitialized";
-static constexpr const char* kInitializedString = "kInitialized";
-static constexpr const char* kClosedString = "kClosed";
-
-static const char* GetNativeBridgeStateString(NativeBridgeState state) {
-  switch (state) {
-    case NativeBridgeState::kNotSetup:
-      return kNotSetupString;
-
-    case NativeBridgeState::kOpened:
-      return kOpenedString;
-
-    case NativeBridgeState::kPreInitialized:
-      return kPreInitializedString;
-
-    case NativeBridgeState::kInitialized:
-      return kInitializedString;
-
-    case NativeBridgeState::kClosed:
-      return kClosedString;
-  }
-}
-
-// Current state of the native bridge.
-static NativeBridgeState state = NativeBridgeState::kNotSetup;
-
-// The version of NativeBridge implementation.
-// Different Nativebridge interface needs the service of different version of
-// Nativebridge implementation.
-// Used by isCompatibleWith() which is introduced in v2.
-enum NativeBridgeImplementationVersion {
-  // first version, not used.
-  DEFAULT_VERSION = 1,
-  // The version which signal semantic is introduced.
-  SIGNAL_VERSION = 2,
-  // The version which namespace semantic is introduced.
-  NAMESPACE_VERSION = 3,
-  // The version with vendor namespaces
-  VENDOR_NAMESPACE_VERSION = 4,
-  // The version with runtime namespaces
-  RUNTIME_NAMESPACE_VERSION = 5,
-};
-
-// Whether we had an error at some point.
-static bool had_error = false;
-
-// Handle of the loaded library.
-static void* native_bridge_handle = nullptr;
-// Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized
-// later.
-static const NativeBridgeCallbacks* callbacks = nullptr;
-// Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge.
-static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr;
-
-// The app's code cache directory.
-static char* app_code_cache_dir = nullptr;
-
-// Code cache directory (relative to the application private directory)
-// Ideally we'd like to call into framework to retrieve this name. However that's considered an
-// implementation detail and will require either hacks or consistent refactorings. We compromise
-// and hard code the directory name again here.
-static constexpr const char* kCodeCacheDir = "code_cache";
-
-// Characters allowed in a native bridge filename. The first character must
-// be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-].
-static bool CharacterAllowed(char c, bool first) {
-  if (first) {
-    return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
-  } else {
-    return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
-           (c == '.') || (c == '_') || (c == '-');
-  }
-}
-
-static void ReleaseAppCodeCacheDir() {
-  if (app_code_cache_dir != nullptr) {
-    delete[] app_code_cache_dir;
-    app_code_cache_dir = nullptr;
-  }
-}
-
-// We only allow simple names for the library. It is supposed to be a file in
-// /system/lib or /vendor/lib. Only allow a small range of characters, that is
-// names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z].
-bool NativeBridgeNameAcceptable(const char* nb_library_filename) {
-  const char* ptr = nb_library_filename;
-  if (*ptr == 0) {
-    // Emptry string. Allowed, means no native bridge.
-    return true;
-  } else {
-    // First character must be [a-zA-Z].
-    if (!CharacterAllowed(*ptr, true))  {
-      // Found an invalid fist character, don't accept.
-      ALOGE("Native bridge library %s has been rejected for first character %c",
-            nb_library_filename,
-            *ptr);
-      return false;
-    } else {
-      // For the rest, be more liberal.
-      ptr++;
-      while (*ptr != 0) {
-        if (!CharacterAllowed(*ptr, false)) {
-          // Found an invalid character, don't accept.
-          ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr);
-          return false;
-        }
-        ptr++;
-      }
-    }
-    return true;
-  }
-}
-
-// The policy of invoking Nativebridge changed in v3 with/without namespace.
-// Suggest Nativebridge implementation not maintain backward-compatible.
-static bool isCompatibleWith(const uint32_t version) {
-  // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported
-  // version.
-  if (callbacks == nullptr || callbacks->version == 0 || version == 0) {
-    return false;
-  }
-
-  // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check.
-  if (callbacks->version >= SIGNAL_VERSION) {
-    return callbacks->isCompatibleWith(version);
-  }
-
-  return true;
-}
-
-static void CloseNativeBridge(bool with_error) {
-  state = NativeBridgeState::kClosed;
-  had_error |= with_error;
-  ReleaseAppCodeCacheDir();
-}
-
-bool LoadNativeBridge(const char* nb_library_filename,
-                      const NativeBridgeRuntimeCallbacks* runtime_cbs) {
-  // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not
-  // multi-threaded, so we do not need locking here.
-
-  if (state != NativeBridgeState::kNotSetup) {
-    // Setup has been called before. Ignore this call.
-    if (nb_library_filename != nullptr) {  // Avoids some log-spam for dalvikvm.
-      ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.",
-            GetNativeBridgeStateString(state));
-    }
-    // Note: counts as an error, even though the bridge may be functional.
-    had_error = true;
-    return false;
-  }
-
-  if (nb_library_filename == nullptr || *nb_library_filename == 0) {
-    CloseNativeBridge(false);
-    return false;
-  } else {
-    if (!NativeBridgeNameAcceptable(nb_library_filename)) {
-      CloseNativeBridge(true);
-    } else {
-      // Try to open the library.
-      void* handle = dlopen(nb_library_filename, RTLD_LAZY);
-      if (handle != nullptr) {
-        callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
-                                                                   kNativeBridgeInterfaceSymbol));
-        if (callbacks != nullptr) {
-          if (isCompatibleWith(NAMESPACE_VERSION)) {
-            // Store the handle for later.
-            native_bridge_handle = handle;
-          } else {
-            callbacks = nullptr;
-            dlclose(handle);
-            ALOGW("Unsupported native bridge interface.");
-          }
-        } else {
-          dlclose(handle);
-        }
-      }
-
-      // Two failure conditions: could not find library (dlopen failed), or could not find native
-      // bridge interface (dlsym failed). Both are an error and close the native bridge.
-      if (callbacks == nullptr) {
-        CloseNativeBridge(true);
-      } else {
-        runtime_callbacks = runtime_cbs;
-        state = NativeBridgeState::kOpened;
-      }
-    }
-    return state == NativeBridgeState::kOpened;
-  }
-}
-
-bool NeedsNativeBridge(const char* instruction_set) {
-  if (instruction_set == nullptr) {
-    ALOGE("Null instruction set in NeedsNativeBridge.");
-    return false;
-  }
-  return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
-}
-
-bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
-  if (state != NativeBridgeState::kOpened) {
-    ALOGE("Invalid state: native bridge is expected to be opened.");
-    CloseNativeBridge(true);
-    return false;
-  }
-
-  if (app_data_dir_in == nullptr) {
-    ALOGE("Application private directory cannot be null.");
-    CloseNativeBridge(true);
-    return false;
-  }
-
-  // Create the path to the application code cache directory.
-  // The memory will be release after Initialization or when the native bridge is closed.
-  const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/'
-  app_code_cache_dir = new char[len];
-  snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir);
-
-  // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo.
-  // Failure is not fatal and will keep the native bridge in kPreInitialized.
-  state = NativeBridgeState::kPreInitialized;
-
-#ifndef __APPLE__
-  if (instruction_set == nullptr) {
-    return true;
-  }
-  size_t isa_len = strlen(instruction_set);
-  if (isa_len > 10) {
-    // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for
-    // x86_64 [including the trailing \0]). This is so we don't have to change here if there will
-    // be another instruction set in the future.
-    ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.",
-          instruction_set);
-    return true;
-  }
-
-  // If the file does not exist, the mount command will fail,
-  // so we save the extra file existence check.
-  char cpuinfo_path[1024];
-
-#if defined(__ANDROID__)
-  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib"
-#ifdef __LP64__
-      "64"
-#endif  // __LP64__
-      "/%s/cpuinfo", instruction_set);
-#else   // !__ANDROID__
-  // To be able to test on the host, we hardwire a relative path.
-  snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo");
-#endif
-
-  // Bind-mount.
-  if (TEMP_FAILURE_RETRY(mount(cpuinfo_path,        // Source.
-                               "/proc/cpuinfo",     // Target.
-                               nullptr,             // FS type.
-                               MS_BIND,             // Mount flags: bind mount.
-                               nullptr)) == -1) {   // "Data."
-    ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno));
-  }
-#else  // __APPLE__
-  UNUSED(instruction_set);
-  ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible.");
-#endif
-
-  return true;
-}
-
-static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) {
-  if (value != nullptr) {
-    jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;");
-    if (field_id == nullptr) {
-      env->ExceptionClear();
-      ALOGW("Could not find %s field.", field);
-      return;
-    }
-
-    jstring str = env->NewStringUTF(value);
-    if (str == nullptr) {
-      env->ExceptionClear();
-      ALOGW("Could not create string %s.", value);
-      return;
-    }
-
-    env->SetStaticObjectField(build_class, field_id, str);
-  }
-}
-
-// Set up the environment for the bridged app.
-static void SetupEnvironment(const NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) {
-  // Need a JNIEnv* to do anything.
-  if (env == nullptr) {
-    ALOGW("No JNIEnv* to set up app environment.");
-    return;
-  }
-
-  // Query the bridge for environment values.
-  const struct NativeBridgeRuntimeValues* env_values = callbacks->getAppEnv(isa);
-  if (env_values == nullptr) {
-    return;
-  }
-
-  // Keep the JNIEnv clean.
-  jint success = env->PushLocalFrame(16);  // That should be small and large enough.
-  if (success < 0) {
-    // Out of memory, really borked.
-    ALOGW("Out of memory while setting up app environment.");
-    env->ExceptionClear();
-    return;
-  }
-
-  // Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge.
-  if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr ||
-      env_values->abi_count >= 0) {
-    jclass bclass_id = env->FindClass("android/os/Build");
-    if (bclass_id != nullptr) {
-      SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi);
-      SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2);
-    } else {
-      // For example in a host test environment.
-      env->ExceptionClear();
-      ALOGW("Could not find Build class.");
-    }
-  }
-
-  if (env_values->os_arch != nullptr) {
-    jclass sclass_id = env->FindClass("java/lang/System");
-    if (sclass_id != nullptr) {
-      jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "setUnchangeableSystemProperty",
-          "(Ljava/lang/String;Ljava/lang/String;)V");
-      if (set_prop_id != nullptr) {
-        // Init os.arch to the value reqired by the apps running with native bridge.
-        env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"),
-            env->NewStringUTF(env_values->os_arch));
-      } else {
-        env->ExceptionClear();
-        ALOGW("Could not find System#setUnchangeableSystemProperty.");
-      }
-    } else {
-      env->ExceptionClear();
-      ALOGW("Could not find System class.");
-    }
-  }
-
-  // Make it pristine again.
-  env->PopLocalFrame(nullptr);
-}
-
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
-  // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that
-  // point we are not multi-threaded, so we do not need locking here.
-
-  if (state == NativeBridgeState::kPreInitialized) {
-    // Check for code cache: if it doesn't exist try to create it.
-    struct stat st;
-    if (stat(app_code_cache_dir, &st) == -1) {
-      if (errno == ENOENT) {
-        if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) {
-          ALOGW("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
-          ReleaseAppCodeCacheDir();
-        }
-      } else {
-        ALOGW("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno));
-        ReleaseAppCodeCacheDir();
-      }
-    } else if (!S_ISDIR(st.st_mode)) {
-      ALOGW("Code cache is not a directory %s.", app_code_cache_dir);
-      ReleaseAppCodeCacheDir();
-    }
-
-    // If we're still PreInitialized (dind't fail the code cache checks) try to initialize.
-    if (state == NativeBridgeState::kPreInitialized) {
-      if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) {
-        SetupEnvironment(callbacks, env, instruction_set);
-        state = NativeBridgeState::kInitialized;
-        // We no longer need the code cache path, release the memory.
-        ReleaseAppCodeCacheDir();
-      } else {
-        // Unload the library.
-        dlclose(native_bridge_handle);
-        CloseNativeBridge(true);
-      }
-    }
-  } else {
-    CloseNativeBridge(true);
-  }
-
-  return state == NativeBridgeState::kInitialized;
-}
-
-void UnloadNativeBridge() {
-  // We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that
-  // point we are not multi-threaded, so we do not need locking here.
-
-  switch(state) {
-    case NativeBridgeState::kOpened:
-    case NativeBridgeState::kPreInitialized:
-    case NativeBridgeState::kInitialized:
-      // Unload.
-      dlclose(native_bridge_handle);
-      CloseNativeBridge(false);
-      break;
-
-    case NativeBridgeState::kNotSetup:
-      // Not even set up. Error.
-      CloseNativeBridge(true);
-      break;
-
-    case NativeBridgeState::kClosed:
-      // Ignore.
-      break;
-  }
-}
-
-bool NativeBridgeError() {
-  return had_error;
-}
-
-bool NativeBridgeAvailable() {
-  return state == NativeBridgeState::kOpened
-      || state == NativeBridgeState::kPreInitialized
-      || state == NativeBridgeState::kInitialized;
-}
-
-bool NativeBridgeInitialized() {
-  // Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after
-  // Runtime::DidForkFromZygote. In that case we do not need a lock.
-  return state == NativeBridgeState::kInitialized;
-}
-
-void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
-  if (NativeBridgeInitialized()) {
-    return callbacks->loadLibrary(libpath, flag);
-  }
-  return nullptr;
-}
-
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty,
-                                uint32_t len) {
-  if (NativeBridgeInitialized()) {
-    return callbacks->getTrampoline(handle, name, shorty, len);
-  }
-  return nullptr;
-}
-
-bool NativeBridgeIsSupported(const char* libpath) {
-  if (NativeBridgeInitialized()) {
-    return callbacks->isSupported(libpath);
-  }
-  return false;
-}
-
-uint32_t NativeBridgeGetVersion() {
-  if (NativeBridgeAvailable()) {
-    return callbacks->version;
-  }
-  return 0;
-}
-
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(SIGNAL_VERSION)) {
-      return callbacks->getSignalHandler(signal);
-    } else {
-      ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION);
-    }
-  }
-  return nullptr;
-}
-
-int NativeBridgeUnloadLibrary(void* handle) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->unloadLibrary(handle);
-    } else {
-      ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION);
-    }
-  }
-  return -1;
-}
-
-const char* NativeBridgeGetError() {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->getError();
-    } else {
-      return "native bridge implementation is not compatible with version 3, cannot get message";
-    }
-  }
-  return "native bridge is not initialized";
-}
-
-bool NativeBridgeIsPathSupported(const char* path) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->isPathSupported(path);
-    } else {
-      ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION);
-    }
-  }
-  return false;
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
-                                        const char* anon_ns_library_path) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path);
-    } else {
-      ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
-    }
-  }
-
-  return false;
-}
-
-native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
-                                                       const char* ld_library_path,
-                                                       const char* default_library_path,
-                                                       uint64_t type,
-                                                       const char* permitted_when_isolated_path,
-                                                       native_bridge_namespace_t* parent_ns) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->createNamespace(name,
-                                        ld_library_path,
-                                        default_library_path,
-                                        type,
-                                        permitted_when_isolated_path,
-                                        parent_ns);
-    } else {
-      ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name);
-    }
-  }
-
-  return nullptr;
-}
-
-bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
-                                const char* shared_libs_sonames) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->linkNamespaces(from, to, shared_libs_sonames);
-    } else {
-      ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION);
-    }
-  }
-
-  return false;
-}
-
-native_bridge_namespace_t* NativeBridgeGetExportedNamespace(const char* name) {
-  if (!NativeBridgeInitialized()) {
-    return nullptr;
-  }
-
-  if (isCompatibleWith(RUNTIME_NAMESPACE_VERSION)) {
-    return callbacks->getExportedNamespace(name);
-  }
-
-  // sphal is vendor namespace name -> use v4 callback in the case NB callbacks
-  // are not compatible with v5
-  if (isCompatibleWith(VENDOR_NAMESPACE_VERSION) && name != nullptr && strcmp("sphal", name) == 0) {
-    return callbacks->getVendorNamespace();
-  }
-
-  return nullptr;
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
-  if (NativeBridgeInitialized()) {
-    if (isCompatibleWith(NAMESPACE_VERSION)) {
-      return callbacks->loadLibraryExt(libpath, flag, ns);
-    } else {
-      ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION);
-    }
-  }
-  return nullptr;
-}
-
-}  // extern "C"
-
-}  // namespace android
diff --git a/libnativebridge/native_bridge_lazy.cc b/libnativebridge/native_bridge_lazy.cc
deleted file mode 100644
index 94c8084..0000000
--- a/libnativebridge/native_bridge_lazy.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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 "nativebridge/native_bridge.h"
-#define LOG_TAG "nativebridge"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace {
-
-void* GetLibHandle() {
-  static void* handle = dlopen("libnativebridge.so", RTLD_NOW);
-  LOG_FATAL_IF(handle == nullptr, "Failed to load libnativebridge.so: %s", dlerror());
-  return handle;
-}
-
-template <typename FuncPtr>
-FuncPtr GetFuncPtr(const char* function_name) {
-  auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
-  LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
-  return f;
-}
-
-#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
-
-}  // namespace
-
-bool LoadNativeBridge(const char* native_bridge_library_filename,
-                      const struct NativeBridgeRuntimeCallbacks* runtime_callbacks) {
-  static auto f = GET_FUNC_PTR(LoadNativeBridge);
-  return f(native_bridge_library_filename, runtime_callbacks);
-}
-
-bool NeedsNativeBridge(const char* instruction_set) {
-  static auto f = GET_FUNC_PTR(NeedsNativeBridge);
-  return f(instruction_set);
-}
-
-bool PreInitializeNativeBridge(const char* app_data_dir, const char* instruction_set) {
-  static auto f = GET_FUNC_PTR(PreInitializeNativeBridge);
-  return f(app_data_dir, instruction_set);
-}
-
-bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
-  static auto f = GET_FUNC_PTR(InitializeNativeBridge);
-  return f(env, instruction_set);
-}
-
-void UnloadNativeBridge() {
-  static auto f = GET_FUNC_PTR(UnloadNativeBridge);
-  return f();
-}
-
-bool NativeBridgeAvailable() {
-  static auto f = GET_FUNC_PTR(NativeBridgeAvailable);
-  return f();
-}
-
-bool NativeBridgeInitialized() {
-  static auto f = GET_FUNC_PTR(NativeBridgeInitialized);
-  return f();
-}
-
-void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
-  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibrary);
-  return f(libpath, flag);
-}
-
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len) {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetTrampoline);
-  return f(handle, name, shorty, len);
-}
-
-bool NativeBridgeIsSupported(const char* libpath) {
-  static auto f = GET_FUNC_PTR(NativeBridgeIsSupported);
-  return f(libpath);
-}
-
-uint32_t NativeBridgeGetVersion() {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetVersion);
-  return f();
-}
-
-NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetSignalHandler);
-  return f(signal);
-}
-
-bool NativeBridgeError() {
-  static auto f = GET_FUNC_PTR(NativeBridgeError);
-  return f();
-}
-
-bool NativeBridgeNameAcceptable(const char* native_bridge_library_filename) {
-  static auto f = GET_FUNC_PTR(NativeBridgeNameAcceptable);
-  return f(native_bridge_library_filename);
-}
-
-int NativeBridgeUnloadLibrary(void* handle) {
-  static auto f = GET_FUNC_PTR(NativeBridgeUnloadLibrary);
-  return f(handle);
-}
-
-const char* NativeBridgeGetError() {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetError);
-  return f();
-}
-
-bool NativeBridgeIsPathSupported(const char* path) {
-  static auto f = GET_FUNC_PTR(NativeBridgeIsPathSupported);
-  return f(path);
-}
-
-bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames,
-                                        const char* anon_ns_library_path) {
-  static auto f = GET_FUNC_PTR(NativeBridgeInitAnonymousNamespace);
-  return f(public_ns_sonames, anon_ns_library_path);
-}
-
-struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
-    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
-    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns) {
-  static auto f = GET_FUNC_PTR(NativeBridgeCreateNamespace);
-  return f(name, ld_library_path, default_library_path, type, permitted_when_isolated_path,
-           parent_ns);
-}
-
-bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
-                                struct native_bridge_namespace_t* to,
-                                const char* shared_libs_sonames) {
-  static auto f = GET_FUNC_PTR(NativeBridgeLinkNamespaces);
-  return f(from, to, shared_libs_sonames);
-}
-
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
-                                 struct native_bridge_namespace_t* ns) {
-  static auto f = GET_FUNC_PTR(NativeBridgeLoadLibraryExt);
-  return f(libpath, flag, ns);
-}
-
-struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
-  static auto f = GET_FUNC_PTR(NativeBridgeGetVendorNamespace);
-  return f();
-}
-
-#undef GET_FUNC_PTR
-
-}  // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
deleted file mode 100644
index 2bb8467..0000000
--- a/libnativebridge/tests/Android.bp
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Copyright (C) 2017 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: "libnativebridge-dummy-defaults",
-
-    host_supported: true,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-    header_libs: ["libnativebridge-headers"],
-    cppflags: ["-fvisibility=protected"],
-}
-
-cc_library_shared {
-    name: "libnativebridge-dummy",
-    srcs: ["DummyNativeBridge.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
-}
-
-cc_library_shared {
-    name: "libnativebridge2-dummy",
-    srcs: ["DummyNativeBridge2.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
-}
-
-cc_library_shared {
-    name: "libnativebridge3-dummy",
-    srcs: ["DummyNativeBridge3.cpp"],
-    defaults: ["libnativebridge-dummy-defaults"],
-}
-
-// Build the unit tests.
-cc_defaults {
-    name: "libnativebridge-tests-defaults",
-    test_per_src: true,
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    srcs: [
-        "CodeCacheCreate_test.cpp",
-        "CodeCacheExists_test.cpp",
-        "CodeCacheStatFail_test.cpp",
-        "CompleteFlow_test.cpp",
-        "InvalidCharsNativeBridge_test.cpp",
-        "NativeBridge2Signal_test.cpp",
-        "NativeBridgeVersion_test.cpp",
-        "NeedsNativeBridge_test.cpp",
-        "PreInitializeNativeBridge_test.cpp",
-        "PreInitializeNativeBridgeFail1_test.cpp",
-        "PreInitializeNativeBridgeFail2_test.cpp",
-        "ReSetupNativeBridge_test.cpp",
-        "UnavailableNativeBridge_test.cpp",
-        "ValidNameNativeBridge_test.cpp",
-        "NativeBridge3UnloadLibrary_test.cpp",
-        "NativeBridge3GetError_test.cpp",
-        "NativeBridge3IsPathSupported_test.cpp",
-        "NativeBridge3InitAnonymousNamespace_test.cpp",
-        "NativeBridge3CreateNamespace_test.cpp",
-        "NativeBridge3LoadLibraryExt_test.cpp",
-    ],
-
-    shared_libs: [
-        "liblog",
-        "libnativebridge-dummy",
-    ],
-    header_libs: ["libbase_headers"],
-}
-
-cc_test {
-    name: "libnativebridge-tests",
-    defaults: ["libnativebridge-tests-defaults"],
-    host_supported: true,
-    shared_libs: ["libnativebridge"],
-}
-
-cc_test {
-    name: "libnativebridge-lazy-tests",
-    defaults: ["libnativebridge-tests-defaults"],
-    shared_libs: ["libnativebridge_lazy"],
-}
-
-// Build the test for the C API.
-cc_test {
-    name: "libnativebridge-api-tests",
-    host_supported: true,
-    test_per_src: true,
-    srcs: [
-        "NativeBridgeApi.c",
-    ],
-    header_libs: ["libnativebridge-headers"],
-}
diff --git a/libnativebridge/tests/CodeCacheCreate_test.cpp b/libnativebridge/tests/CodeCacheCreate_test.cpp
deleted file mode 100644
index 58270c4..0000000
--- a/libnativebridge/tests/CodeCacheCreate_test.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-namespace android {
-
-// Tests that the bridge initialization creates the code_cache if it doesn't
-// exists.
-TEST_F(NativeBridgeTest, CodeCacheCreate) {
-    // Make sure that code_cache does not exists
-    struct stat st;
-    ASSERT_EQ(-1, stat(kCodeCache, &st));
-    ASSERT_EQ(ENOENT, errno);
-
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_FALSE(NativeBridgeError());
-
-    // Check that code_cache was created
-    ASSERT_EQ(0, stat(kCodeCache, &st));
-    ASSERT_TRUE(S_ISDIR(st.st_mode));
-
-    // Clean up
-    UnloadNativeBridge();
-    ASSERT_EQ(0, rmdir(kCodeCache));
-
-    ASSERT_FALSE(NativeBridgeError());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/CodeCacheExists_test.cpp b/libnativebridge/tests/CodeCacheExists_test.cpp
deleted file mode 100644
index 8ba0158..0000000
--- a/libnativebridge/tests/CodeCacheExists_test.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-namespace android {
-
-// Tests that the bridge is initialized without errors if the code_cache already
-// exists.
-TEST_F(NativeBridgeTest, CodeCacheExists) {
-    // Make sure that code_cache does not exists
-    struct stat st;
-    ASSERT_EQ(-1, stat(kCodeCache, &st));
-    ASSERT_EQ(ENOENT, errno);
-
-    // Create the code_cache
-    ASSERT_EQ(0, mkdir(kCodeCache, S_IRWXU | S_IRWXG | S_IXOTH));
-
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_FALSE(NativeBridgeError());
-
-    // Check that the code cache is still there
-    ASSERT_EQ(0, stat(kCodeCache, &st));
-    ASSERT_TRUE(S_ISDIR(st.st_mode));
-
-    // Clean up
-    UnloadNativeBridge();
-    ASSERT_EQ(0, rmdir(kCodeCache));
-
-    ASSERT_FALSE(NativeBridgeError());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/CodeCacheStatFail_test.cpp b/libnativebridge/tests/CodeCacheStatFail_test.cpp
deleted file mode 100644
index 4ea519e..0000000
--- a/libnativebridge/tests/CodeCacheStatFail_test.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-namespace android {
-
-// Tests that the bridge is initialized without errors if the code_cache is
-// existed as a file.
-TEST_F(NativeBridgeTest, CodeCacheStatFail) {
-    int fd = creat(kCodeCache, O_RDWR);
-    ASSERT_NE(-1, fd);
-    close(fd);
-
-    struct stat st;
-    ASSERT_EQ(-1, stat(kCodeCacheStatFail, &st));
-    ASSERT_EQ(ENOTDIR, errno);
-
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-    ASSERT_TRUE(PreInitializeNativeBridge(kCodeCacheStatFail, "isa"));
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_FALSE(NativeBridgeError());
-
-    // Clean up
-    UnloadNativeBridge();
-
-    ASSERT_FALSE(NativeBridgeError());
-    unlink(kCodeCache);
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/CompleteFlow_test.cpp b/libnativebridge/tests/CompleteFlow_test.cpp
deleted file mode 100644
index b033792..0000000
--- a/libnativebridge/tests/CompleteFlow_test.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <unistd.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, CompleteFlow) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    // Basic calls to check that nothing crashes
-    ASSERT_FALSE(NativeBridgeIsSupported(nullptr));
-    ASSERT_EQ(nullptr, NativeBridgeLoadLibrary(nullptr, 0));
-    ASSERT_EQ(nullptr, NativeBridgeGetTrampoline(nullptr, nullptr, nullptr, 0));
-
-    // Unload
-    UnloadNativeBridge();
-
-    ASSERT_FALSE(NativeBridgeAvailable());
-    ASSERT_FALSE(NativeBridgeError());
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/DummyNativeBridge.cpp b/libnativebridge/tests/DummyNativeBridge.cpp
deleted file mode 100644
index b9894f6..0000000
--- a/libnativebridge/tests/DummyNativeBridge.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                                         const char* /* app_code_cache_dir */,
-                                         const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf {
-  .version = 1,
-  .initialize = &native_bridge_initialize,
-  .loadLibrary = &native_bridge_loadLibrary,
-  .getTrampoline = &native_bridge_getTrampoline,
-  .isSupported = &native_bridge_isSupported,
-  .getAppEnv = &native_bridge_getAppEnv
-};
diff --git a/libnativebridge/tests/DummyNativeBridge2.cpp b/libnativebridge/tests/DummyNativeBridge2.cpp
deleted file mode 100644
index 6920c74..0000000
--- a/libnativebridge/tests/DummyNativeBridge2.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include <signal.h>
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge2_initialize(const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                                         const char* /* app_code_cache_dir */,
-                                         const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge2_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge2_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge2_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge2_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge2_is_compatible_compatible_with(uint32_t version) {
-  // For testing, allow 1 and 2, but disallow 3+.
-  return version <= 2;
-}
-
-static bool native_bridge2_dummy_signal_handler(int, siginfo_t*, void*) {
-  // TODO: Implement something here. We'd either have to have a death test with a log here, or
-  //       we'd have to be able to resume after the faulting instruction...
-  return true;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge2_get_signal_handler(int signal) {
-  if (signal == SIGSEGV) {
-    return &native_bridge2_dummy_signal_handler;
-  }
-  return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf {
-  .version = 2,
-  .initialize = &native_bridge2_initialize,
-  .loadLibrary = &native_bridge2_loadLibrary,
-  .getTrampoline = &native_bridge2_getTrampoline,
-  .isSupported = &native_bridge2_isSupported,
-  .getAppEnv = &native_bridge2_getAppEnv,
-  .isCompatibleWith = &native_bridge2_is_compatible_compatible_with,
-  .getSignalHandler = &native_bridge2_get_signal_handler
-};
-
diff --git a/libnativebridge/tests/DummyNativeBridge3.cpp b/libnativebridge/tests/DummyNativeBridge3.cpp
deleted file mode 100644
index 4ef1c82..0000000
--- a/libnativebridge/tests/DummyNativeBridge3.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-// A dummy implementation of the native-bridge interface.
-
-#include "nativebridge/native_bridge.h"
-
-#include <signal.h>
-
-// NativeBridgeCallbacks implementations
-extern "C" bool native_bridge3_initialize(
-                      const android::NativeBridgeRuntimeCallbacks* /* art_cbs */,
-                      const char* /* app_code_cache_dir */,
-                      const char* /* isa */) {
-  return true;
-}
-
-extern "C" void* native_bridge3_loadLibrary(const char* /* libpath */, int /* flag */) {
-  return nullptr;
-}
-
-extern "C" void* native_bridge3_getTrampoline(void* /* handle */, const char* /* name */,
-                                             const char* /* shorty */, uint32_t /* len */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_isSupported(const char* /* libpath */) {
-  return false;
-}
-
-extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge3_getAppEnv(
-    const char* /* abi */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_isCompatibleWith(uint32_t version) {
-  // For testing, allow 1-3, but disallow 4+.
-  return version <= 3;
-}
-
-static bool native_bridge3_dummy_signal_handler(int, siginfo_t*, void*) {
-  // TODO: Implement something here. We'd either have to have a death test with a log here, or
-  //       we'd have to be able to resume after the faulting instruction...
-  return true;
-}
-
-extern "C" android::NativeBridgeSignalHandlerFn native_bridge3_getSignalHandler(int signal) {
-  if (signal == SIGSEGV) {
-    return &native_bridge3_dummy_signal_handler;
-  }
-  return nullptr;
-}
-
-extern "C" int native_bridge3_unloadLibrary(void* /* handle */) {
-  return 0;
-}
-
-extern "C" const char* native_bridge3_getError() {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_isPathSupported(const char* /* path */) {
-  return true;
-}
-
-extern "C" bool native_bridge3_initAnonymousNamespace(const char* /* public_ns_sonames */,
-                                                      const char* /* anon_ns_library_path */) {
-  return true;
-}
-
-extern "C" android::native_bridge_namespace_t*
-native_bridge3_createNamespace(const char* /* name */,
-                               const char* /* ld_library_path */,
-                               const char* /* default_library_path */,
-                               uint64_t /* type */,
-                               const char* /* permitted_when_isolated_path */,
-                               android::native_bridge_namespace_t* /* parent_ns */) {
-  return nullptr;
-}
-
-extern "C" bool native_bridge3_linkNamespaces(android::native_bridge_namespace_t* /* from */,
-                                              android::native_bridge_namespace_t* /* to */,
-                                              const char* /* shared_libs_soname */) {
-  return true;
-}
-
-extern "C" void* native_bridge3_loadLibraryExt(const char* /* libpath */,
-                                               int /* flag */,
-                                               android::native_bridge_namespace_t* /* ns */) {
-  return nullptr;
-}
-
-android::NativeBridgeCallbacks NativeBridgeItf{
-    // v1
-    .version = 3,
-    .initialize = &native_bridge3_initialize,
-    .loadLibrary = &native_bridge3_loadLibrary,
-    .getTrampoline = &native_bridge3_getTrampoline,
-    .isSupported = &native_bridge3_isSupported,
-    .getAppEnv = &native_bridge3_getAppEnv,
-    // v2
-    .isCompatibleWith = &native_bridge3_isCompatibleWith,
-    .getSignalHandler = &native_bridge3_getSignalHandler,
-    // v3
-    .unloadLibrary = &native_bridge3_unloadLibrary,
-    .getError = &native_bridge3_getError,
-    .isPathSupported = &native_bridge3_isPathSupported,
-    .initAnonymousNamespace = &native_bridge3_initAnonymousNamespace,
-    .createNamespace = &native_bridge3_createNamespace,
-    .linkNamespaces = &native_bridge3_linkNamespaces,
-    .loadLibraryExt = &native_bridge3_loadLibraryExt};
diff --git a/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp b/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp
deleted file mode 100644
index 8f7973d..0000000
--- a/libnativebridge/tests/InvalidCharsNativeBridge_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-namespace android {
-
-static const char* kTestName = "../librandom$@-bridge_not.existing.so";
-
-TEST_F(NativeBridgeTest, InvalidChars) {
-    // Do one test actually calling setup.
-    EXPECT_EQ(false, NativeBridgeError());
-    LoadNativeBridge(kTestName, nullptr);
-    // This should lead to an error for invalid characters.
-    EXPECT_EQ(true, NativeBridgeError());
-
-    // Further tests need to use NativeBridgeNameAcceptable, as the error
-    // state can't be changed back.
-    EXPECT_EQ(false, NativeBridgeNameAcceptable("."));
-    EXPECT_EQ(false, NativeBridgeNameAcceptable(".."));
-    EXPECT_EQ(false, NativeBridgeNameAcceptable("_"));
-    EXPECT_EQ(false, NativeBridgeNameAcceptable("-"));
-    EXPECT_EQ(false, NativeBridgeNameAcceptable("lib@.so"));
-    EXPECT_EQ(false, NativeBridgeNameAcceptable("lib$.so"));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge2Signal_test.cpp b/libnativebridge/tests/NativeBridge2Signal_test.cpp
deleted file mode 100644
index 44e45e3..0000000
--- a/libnativebridge/tests/NativeBridge2Signal_test.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <signal.h>
-#include <unistd.h>
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
-
-TEST_F(NativeBridgeTest, V2_Signal) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary2, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    ASSERT_EQ(2U, NativeBridgeGetVersion());
-    ASSERT_NE(nullptr, NativeBridgeGetSignalHandler(SIGSEGV));
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp b/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
deleted file mode 100644
index 668d942..0000000
--- a/libnativebridge/tests/NativeBridge3CreateNamespace_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_CreateNamespace) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    ASSERT_EQ(3U, NativeBridgeGetVersion());
-    ASSERT_EQ(nullptr, NativeBridgeCreateNamespace(nullptr, nullptr, nullptr,
-                                                   0, nullptr, nullptr));
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge3GetError_test.cpp b/libnativebridge/tests/NativeBridge3GetError_test.cpp
deleted file mode 100644
index 0b9f582..0000000
--- a/libnativebridge/tests/NativeBridge3GetError_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_GetError) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    ASSERT_EQ(3U, NativeBridgeGetVersion());
-    ASSERT_EQ(nullptr, NativeBridgeGetError());
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp b/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
deleted file mode 100644
index b0d6b09..0000000
--- a/libnativebridge/tests/NativeBridge3InitAnonymousNamespace_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_InitAnonymousNamespace) {
-  // Init
-  ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
-  ASSERT_TRUE(NativeBridgeAvailable());
-  ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-  ASSERT_TRUE(NativeBridgeAvailable());
-  ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-  ASSERT_TRUE(NativeBridgeAvailable());
-
-  ASSERT_EQ(3U, NativeBridgeGetVersion());
-  ASSERT_EQ(true, NativeBridgeInitAnonymousNamespace(nullptr, nullptr));
-
-  // Clean-up code_cache
-  ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp b/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
deleted file mode 100644
index 325e40b..0000000
--- a/libnativebridge/tests/NativeBridge3IsPathSupported_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_IsPathSupported) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    ASSERT_EQ(3U, NativeBridgeGetVersion());
-    ASSERT_EQ(true, NativeBridgeIsPathSupported(nullptr));
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp b/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
deleted file mode 100644
index 4caeb44..0000000
--- a/libnativebridge/tests/NativeBridge3LoadLibraryExt_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_LoadLibraryExt) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    ASSERT_EQ(3U, NativeBridgeGetVersion());
-    ASSERT_EQ(nullptr, NativeBridgeLoadLibraryExt(nullptr, 0, nullptr));
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp b/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
deleted file mode 100644
index 93a979c..0000000
--- a/libnativebridge/tests/NativeBridge3UnloadLibrary_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 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 "NativeBridgeTest.h"
-
-namespace android {
-
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-TEST_F(NativeBridgeTest, V3_UnloadLibrary) {
-    // Init
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary3, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(PreInitializeNativeBridge(".", "isa"));
-    ASSERT_TRUE(NativeBridgeAvailable());
-    ASSERT_TRUE(InitializeNativeBridge(nullptr, nullptr));
-    ASSERT_TRUE(NativeBridgeAvailable());
-
-    ASSERT_EQ(3U, NativeBridgeGetVersion());
-    ASSERT_EQ(0, NativeBridgeUnloadLibrary(nullptr));
-
-    // Clean-up code_cache
-    ASSERT_EQ(0, rmdir(kCodeCache));
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NativeBridgeApi.c b/libnativebridge/tests/NativeBridgeApi.c
deleted file mode 100644
index 7ab71fe..0000000
--- a/libnativebridge/tests/NativeBridgeApi.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-/* The main purpose of this test is to ensure this C header compiles in C, so
- * that no C++ features inadvertently leak into the C ABI. */
-#include "nativebridge/native_bridge.h"
-
-int main(int argc, char** argv) {
-  (void)argc;
-  (void)argv;
-  return 0;
-}
diff --git a/libnativebridge/tests/NativeBridgeTest.h b/libnativebridge/tests/NativeBridgeTest.h
deleted file mode 100644
index 0f99816..0000000
--- a/libnativebridge/tests/NativeBridgeTest.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 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 NATIVE_BRIDGE_TEST_H_
-#define NATIVE_BRIDGE_TEST_H_
-
-#define LOG_TAG "NativeBridge_test"
-
-#include <nativebridge/native_bridge.h>
-#include <gtest/gtest.h>
-
-constexpr const char* kNativeBridgeLibrary = "libnativebridge-dummy.so";
-constexpr const char* kCodeCache = "./code_cache";
-constexpr const char* kCodeCacheStatFail = "./code_cache/temp";
-constexpr const char* kNativeBridgeLibrary2 = "libnativebridge2-dummy.so";
-constexpr const char* kNativeBridgeLibrary3 = "libnativebridge3-dummy.so";
-
-namespace android {
-
-class NativeBridgeTest : public testing::Test {
-};
-
-};  // namespace android
-
-#endif  // NATIVE_BRIDGE_H_
-
diff --git a/libnativebridge/tests/NativeBridgeVersion_test.cpp b/libnativebridge/tests/NativeBridgeVersion_test.cpp
deleted file mode 100644
index d3f9a80..0000000
--- a/libnativebridge/tests/NativeBridgeVersion_test.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 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 "NativeBridgeTest.h"
-
-#include <unistd.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, Version) {
-    // When a bridge isn't loaded, we expect 0.
-    EXPECT_EQ(NativeBridgeGetVersion(), 0U);
-
-    // After our dummy bridge has been loaded, we expect 1.
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-    EXPECT_EQ(NativeBridgeGetVersion(), 1U);
-
-    // Unload
-    UnloadNativeBridge();
-
-    // Version information is gone.
-    EXPECT_EQ(NativeBridgeGetVersion(), 0U);
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/NeedsNativeBridge_test.cpp b/libnativebridge/tests/NeedsNativeBridge_test.cpp
deleted file mode 100644
index c8ff743..0000000
--- a/libnativebridge/tests/NeedsNativeBridge_test.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <android-base/macros.h>
-
-namespace android {
-
-static const char* kISAs[] = { "arm", "arm64", "mips", "mips64", "x86", "x86_64", "random", "64arm",
-                               "64_x86", "64_x86_64", "", "reallylongstringabcd", nullptr };
-
-TEST_F(NativeBridgeTest, NeedsNativeBridge) {
-  EXPECT_EQ(false, NeedsNativeBridge(ABI_STRING));
-
-  const size_t kISACount = sizeof(kISAs) / sizeof(kISAs[0]);
-  for (size_t i = 0; i < kISACount; i++) {
-    EXPECT_EQ(kISAs[i] == nullptr ? false : strcmp(kISAs[i], ABI_STRING) != 0,
-              NeedsNativeBridge(kISAs[i]));
-    }
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
deleted file mode 100644
index 5a2b0a1..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridgeFail1_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail1) {
-  // Needs a valid application directory.
-  ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-  ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
-  ASSERT_TRUE(NativeBridgeError());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp b/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp
deleted file mode 100644
index af976b1..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridgeFail2_test.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 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 <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-#include "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridgeFail2) {
-  // Needs LoadNativeBridge() first
-  ASSERT_FALSE(PreInitializeNativeBridge(nullptr, "isa"));
-  ASSERT_TRUE(NativeBridgeError());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp b/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
deleted file mode 100644
index cd5a8e2..0000000
--- a/libnativebridge/tests/PreInitializeNativeBridge_test.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2014 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 <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <cstdio>
-#include <cstring>
-
-#include <android/log.h>
-
-#include "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, PreInitializeNativeBridge) {
-    ASSERT_TRUE(LoadNativeBridge(kNativeBridgeLibrary, nullptr));
-#if !defined(__APPLE__)         // Mac OS does not support bind-mount.
-#if !defined(__ANDROID__)       // Cannot write into the hard-wired location.
-    static constexpr const char* kTestData = "PreInitializeNativeBridge test.";
-
-    // Try to create our mount namespace.
-    if (unshare(CLONE_NEWNS) != -1) {
-        // Create a dummy file.
-        FILE* cpuinfo = fopen("./cpuinfo", "w");
-        ASSERT_NE(nullptr, cpuinfo) << strerror(errno);
-        fprintf(cpuinfo, kTestData);
-        fclose(cpuinfo);
-
-        ASSERT_TRUE(PreInitializeNativeBridge("does not matter 1", "short 2"));
-
-        // Read /proc/cpuinfo
-        FILE* proc_cpuinfo = fopen("/proc/cpuinfo", "r");
-        ASSERT_NE(nullptr, proc_cpuinfo) << strerror(errno);
-        char buf[1024];
-        EXPECT_NE(nullptr, fgets(buf, sizeof(buf), proc_cpuinfo)) << "Error reading.";
-        fclose(proc_cpuinfo);
-
-        EXPECT_EQ(0, strcmp(buf, kTestData));
-
-        // Delete the file.
-        ASSERT_EQ(0, unlink("./cpuinfo")) << "Error unlinking temporary file.";
-        // Ending the test will tear down the mount namespace.
-    } else {
-        GTEST_LOG_(WARNING) << "Could not create mount namespace. Are you running this as root?";
-    }
-#endif
-#endif
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/ReSetupNativeBridge_test.cpp b/libnativebridge/tests/ReSetupNativeBridge_test.cpp
deleted file mode 100644
index 944e5d7..0000000
--- a/libnativebridge/tests/ReSetupNativeBridge_test.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2014 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 "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, ReSetup) {
-    EXPECT_EQ(false, NativeBridgeError());
-    LoadNativeBridge("", nullptr);
-    EXPECT_EQ(false, NativeBridgeError());
-    LoadNativeBridge("", nullptr);
-    // This should lead to an error for trying to re-setup a native bridge.
-    EXPECT_EQ(true, NativeBridgeError());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/UnavailableNativeBridge_test.cpp b/libnativebridge/tests/UnavailableNativeBridge_test.cpp
deleted file mode 100644
index ad374a5..0000000
--- a/libnativebridge/tests/UnavailableNativeBridge_test.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011 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 "NativeBridgeTest.h"
-
-namespace android {
-
-TEST_F(NativeBridgeTest, NoNativeBridge) {
-    EXPECT_EQ(false, NativeBridgeAvailable());
-    // Try to initialize. This should fail as we are not set up.
-    EXPECT_EQ(false, InitializeNativeBridge(nullptr, nullptr));
-    EXPECT_EQ(true, NativeBridgeError());
-    EXPECT_EQ(false, NativeBridgeAvailable());
-}
-
-}  // namespace android
diff --git a/libnativebridge/tests/ValidNameNativeBridge_test.cpp b/libnativebridge/tests/ValidNameNativeBridge_test.cpp
deleted file mode 100644
index 690be4a..0000000
--- a/libnativebridge/tests/ValidNameNativeBridge_test.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2011 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 <NativeBridgeTest.h>
-
-namespace android {
-
-static const char* kTestName = "librandom-bridge_not.existing.so";
-
-TEST_F(NativeBridgeTest, ValidName) {
-    // Check that the name is acceptable.
-    EXPECT_EQ(true, NativeBridgeNameAcceptable(kTestName));
-
-    // Now check what happens on LoadNativeBridge.
-    EXPECT_EQ(false, NativeBridgeError());
-    LoadNativeBridge(kTestName, nullptr);
-    // This will lead to an error as the library doesn't exist.
-    EXPECT_EQ(true, NativeBridgeError());
-    EXPECT_EQ(false, NativeBridgeAvailable());
-}
-
-}  // namespace android
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
deleted file mode 100644
index 66cb49f..0000000
--- a/libnativeloader/Android.bp
+++ /dev/null
@@ -1,65 +0,0 @@
-// Shared library for target
-// ========================================================
-cc_defaults {
-    name: "libnativeloader-defaults",
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    cppflags: [
-        "-fvisibility=hidden",
-    ],
-    header_libs: ["libnativeloader-headers"],
-    export_header_lib_headers: ["libnativeloader-headers"],
-}
-
-cc_library {
-    name: "libnativeloader",
-    defaults: ["libnativeloader-defaults"],
-    host_supported: true,
-    srcs: ["native_loader.cpp"],
-    shared_libs: [
-        "libnativehelper",
-        "liblog",
-        "libnativebridge",
-        "libbase",
-    ],
-    target: {
-        android: {
-            shared_libs: [
-                "libdl_android",
-            ],
-        },
-    },
-    required: [
-        "llndk.libraries.txt",
-        "vndksp.libraries.txt",
-    ],
-    stubs: {
-        symbol_file: "libnativeloader.map.txt",
-        versions: ["1"],
-    },
-}
-
-// TODO(b/124250621) eliminate the need for this library
-cc_library {
-    name: "libnativeloader_lazy",
-    defaults: ["libnativeloader-defaults"],
-    host_supported: false,
-    srcs: ["native_loader_lazy.cpp"],
-    required: ["libnativeloader"],
-}
-
-cc_library_headers {
-    name: "libnativeloader-headers",
-    host_supported: true,
-    export_include_dirs: ["include"],
-}
-
-// TODO(jiyong) Remove this when its use in the internal master is
-// switched to libnativeloader-headers
-cc_library_headers {
-    name: "libnativeloader-dummy-headers",
-    host_supported: true,
-    export_include_dirs: ["include"],
-}
diff --git a/libnativeloader/OWNERS b/libnativeloader/OWNERS
deleted file mode 100644
index f735653..0000000
--- a/libnativeloader/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-dimitry@google.com
-jiyong@google.com
-ngeoffray@google.com
-oth@google.com
-mast@google.com
-rpl@google.com
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
deleted file mode 100644
index 2d6ce85..0000000
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2016 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_DLEXT_NAMESPACES_H__
-#define __ANDROID_DLEXT_NAMESPACES_H__
-
-#include <android/dlext.h>
-#include <stdbool.h>
-
-__BEGIN_DECLS
-
-/*
- * Initializes anonymous namespaces. The shared_libs_sonames is the list of sonames
- * to be shared by default namespace separated by colon. Example: "libc.so:libm.so:libdl.so".
- *
- * The library_search_path is the search path for anonymous namespace. The anonymous namespace
- * is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens
- * for the code not loaded by dynamic linker; for example calls from the mono-compiled code.
- */
-extern bool android_init_anonymous_namespace(const char* shared_libs_sonames,
-                                             const char* library_search_path);
-
-
-enum {
-  /* A regular namespace is the namespace with a custom search path that does
-   * not impose any restrictions on the location of native libraries.
-   */
-  ANDROID_NAMESPACE_TYPE_REGULAR = 0,
-
-  /* An isolated namespace requires all the libraries to be on the search path
-   * or under permitted_when_isolated_path. The search path is the union of
-   * ld_library_path and default_library_path.
-   */
-  ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
-
-  /* The shared namespace clones the list of libraries of the caller namespace upon creation
-   * which means that they are shared between namespaces - the caller namespace and the new one
-   * will use the same copy of a library if it was loaded prior to android_create_namespace call.
-   *
-   * Note that libraries loaded after the namespace is created will not be shared.
-   *
-   * Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor
-   * permitted_path from the caller's namespace.
-   */
-  ANDROID_NAMESPACE_TYPE_SHARED = 2,
-
-  /* This flag instructs linker to enable grey-list workaround for the namespace.
-   * See http://b/26394120 for details.
-   */
-  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
-
-  ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
-                                           ANDROID_NAMESPACE_TYPE_ISOLATED,
-};
-
-/*
- * Creates new linker namespace.
- * ld_library_path and default_library_path represent the search path
- * for the libraries in the namespace.
- *
- * The libraries in the namespace are searched by folowing order:
- * 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
- * 2. In directories specified by DT_RUNPATH of the "needed by" binary.
- * 3. deault_library_path (This of this as namespace-local default library path)
- *
- * When type is ANDROID_NAMESPACE_TYPE_ISOLATED the resulting namespace requires all of
- * the libraries to be on the search path or under the permitted_when_isolated_path;
- * the search_path is ld_library_path:default_library_path. Note that the
- * permitted_when_isolated_path path is not part of the search_path and
- * does not affect the search order. It is a way to allow loading libraries from specific
- * locations when using absolute path.
- * If a library or any of its dependencies are outside of the permitted_when_isolated_path
- * and search_path, and it is not part of the public namespace dlopen will fail.
- */
-extern struct android_namespace_t* android_create_namespace(
-    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
-    const char* permitted_when_isolated_path, struct android_namespace_t* parent);
-
-/*
- * Creates a link between namespaces. Every link has list of sonames of
- * shared libraries. These are the libraries which are accessible from
- * namespace 'from' but loaded within namespace 'to' context.
- * When to namespace is nullptr this function establishes a link between
- * 'from' namespace and the default namespace.
- *
- * The lookup order of the libraries in namespaces with links is following:
- * 1. Look inside current namespace using 'this' namespace search path.
- * 2. Look in linked namespaces
- * 2.1. Perform soname check - if library soname is not in the list of shared
- *      libraries sonames skip this link, otherwise
- * 2.2. Search library using linked namespace search path. Note that this
- *      step will not go deeper into linked namespaces for this library but
- *      will do so for DT_NEEDED libraries.
- */
-extern bool android_link_namespaces(struct android_namespace_t* from,
-                                    struct android_namespace_t* to,
-                                    const char* shared_libs_sonames);
-
-extern struct android_namespace_t* android_get_exported_namespace(const char* name);
-
-__END_DECLS
-
-#endif /* __ANDROID_DLEXT_NAMESPACES_H__ */
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
deleted file mode 100644
index 51fb875..0000000
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2015 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 NATIVE_LOADER_H_
-#define NATIVE_LOADER_H_
-
-#include <stdbool.h>
-#include <stdint.h>
-#include "jni.h"
-#if defined(__ANDROID__)
-#include <android/dlext.h>
-#endif
-
-#ifdef __cplusplus
-namespace android {
-extern "C" {
-#endif  // __cplusplus
-
-// README: the char** error message parameter being passed
-// to the methods below need to be freed through calling NativeLoaderFreeErrorMessage.
-// It's the caller's responsibility to call that method.
-
-__attribute__((visibility("default")))
-void InitializeNativeLoader();
-
-__attribute__((visibility("default"))) jstring CreateClassLoaderNamespace(
-    JNIEnv* env, int32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path,
-    jstring library_path, jstring permitted_path);
-
-__attribute__((visibility("default"))) void* OpenNativeLibrary(
-    JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
-    const char* caller_location, jstring library_path, bool* needs_native_bridge, char** error_msg);
-
-__attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle,
-                                                               const bool needs_native_bridge,
-                                                               char** error_msg);
-
-__attribute__((visibility("default"))) void NativeLoaderFreeErrorMessage(char* msg);
-
-#if defined(__ANDROID__)
-// Look up linker namespace by class_loader. Returns nullptr if
-// there is no namespace associated with the class_loader.
-// TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function.
-__attribute__((visibility("default"))) struct android_namespace_t* FindNamespaceByClassLoader(
-    JNIEnv* env, jobject class_loader);
-// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
-struct NativeLoaderNamespace;
-__attribute__((visibility("default"))) struct NativeLoaderNamespace*
-FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
-// Load library.  Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does
-// not require access to JNIEnv either.
-__attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace(
-    struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
-    char** error_msg);
-#endif
-
-__attribute__((visibility("default")))
-void ResetNativeLoader();
-
-#ifdef __cplusplus
-}  // extern "C"
-}  // namespace android
-#endif  // __cplusplus
-
-#endif  // NATIVE_BRIDGE_H_
diff --git a/libnativeloader/libnativeloader.map.txt b/libnativeloader/libnativeloader.map.txt
deleted file mode 100644
index 40c30bd..0000000
--- a/libnativeloader/libnativeloader.map.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# 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.
-#
-
-# TODO(b/122710865): Prune these uses once the runtime APEX is complete.
-LIBNATIVELOADER_1 {
-  global:
-    OpenNativeLibrary;
-    InitializeNativeLoader;
-    ResetNativeLoader;
-    CloseNativeLibrary;
-    OpenNativeLibraryInNamespace;
-    FindNamespaceByClassLoader;
-    FindNativeLoaderNamespaceByClassLoader;
-    CreateClassLoaderNamespace;
-    NativeLoaderFreeErrorMessage;
-  local:
-    *;
-};
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
deleted file mode 100644
index e460b1a..0000000
--- a/libnativeloader/native_loader.cpp
+++ /dev/null
@@ -1,952 +0,0 @@
-/*
- * Copyright (C) 2015 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 "nativeloader/native_loader.h"
-#include <nativehelper/ScopedUtfChars.h>
-
-#include <dlfcn.h>
-#ifdef __ANDROID__
-#define LOG_TAG "libnativeloader"
-#include "nativeloader/dlext_namespaces.h"
-#include "log/log.h"
-#endif
-#include <dirent.h>
-#include <sys/types.h>
-#include "nativebridge/native_bridge.h"
-
-#include <algorithm>
-#include <list>
-#include <memory>
-#include <mutex>
-#include <regex>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/macros.h>
-#include <android-base/strings.h>
-
-#ifdef __BIONIC__
-#include <android-base/properties.h>
-#endif
-
-#define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\
-                                             "%s:%d: %s CHECK '" #predicate "' failed.",\
-                                             __FILE__, __LINE__, __FUNCTION__)
-
-using namespace std::string_literals;
-
-namespace android {
-
-#if defined(__ANDROID__)
-struct NativeLoaderNamespace {
- public:
-  NativeLoaderNamespace()
-      : android_ns_(nullptr), native_bridge_ns_(nullptr) { }
-
-  explicit NativeLoaderNamespace(android_namespace_t* ns)
-      : android_ns_(ns), native_bridge_ns_(nullptr) { }
-
-  explicit NativeLoaderNamespace(native_bridge_namespace_t* ns)
-      : android_ns_(nullptr), native_bridge_ns_(ns) { }
-
-  NativeLoaderNamespace(NativeLoaderNamespace&& that) = default;
-  NativeLoaderNamespace(const NativeLoaderNamespace& that) = default;
-
-  NativeLoaderNamespace& operator=(const NativeLoaderNamespace& that) = default;
-
-  android_namespace_t* get_android_ns() const {
-    CHECK(native_bridge_ns_ == nullptr);
-    return android_ns_;
-  }
-
-  native_bridge_namespace_t* get_native_bridge_ns() const {
-    CHECK(android_ns_ == nullptr);
-    return native_bridge_ns_;
-  }
-
-  bool is_android_namespace() const {
-    return native_bridge_ns_ == nullptr;
-  }
-
- private:
-  // Only one of them can be not null
-  android_namespace_t* android_ns_;
-  native_bridge_namespace_t* native_bridge_ns_;
-};
-
-static constexpr const char kPublicNativeLibrariesSystemConfigPathFromRoot[] =
-    "/etc/public.libraries.txt";
-static constexpr const char kPublicNativeLibrariesExtensionConfigPrefix[] = "public.libraries-";
-static constexpr const size_t kPublicNativeLibrariesExtensionConfigPrefixLen =
-    sizeof(kPublicNativeLibrariesExtensionConfigPrefix) - 1;
-static constexpr const char kPublicNativeLibrariesExtensionConfigSuffix[] = ".txt";
-static constexpr const size_t kPublicNativeLibrariesExtensionConfigSuffixLen =
-    sizeof(kPublicNativeLibrariesExtensionConfigSuffix) - 1;
-static constexpr const char kPublicNativeLibrariesVendorConfig[] =
-    "/vendor/etc/public.libraries.txt";
-static constexpr const char kLlndkNativeLibrariesSystemConfigPathFromRoot[] =
-    "/etc/llndk.libraries.txt";
-static constexpr const char kVndkspNativeLibrariesSystemConfigPathFromRoot[] =
-    "/etc/vndksp.libraries.txt";
-
-static const std::vector<const std::string> kRuntimePublicLibraries = {
-    "libicuuc.so",
-    "libicui18n.so",
-};
-
-// The device may be configured to have the vendor libraries loaded to a separate namespace.
-// For historical reasons this namespace was named sphal but effectively it is intended
-// to use to load vendor libraries to separate namespace with controlled interface between
-// vendor and system namespaces.
-static constexpr const char* kVendorNamespaceName = "sphal";
-
-static constexpr const char* kVndkNamespaceName = "vndk";
-
-static constexpr const char* kDefaultNamespaceName = "default";
-static constexpr const char* kPlatformNamespaceName = "platform";
-static constexpr const char* kRuntimeNamespaceName = "runtime";
-
-// classloader-namespace is a linker namespace that is created for the loaded
-// app. To be specific, it is created for the app classloader. When
-// System.load() is called from a Java class that is loaded from the
-// classloader, the classloader-namespace namespace associated with that
-// classloader is selected for dlopen. The namespace is configured so that its
-// search path is set to the app-local JNI directory and it is linked to the
-// default namespace with the names of libs listed in the public.libraries.txt.
-// This way an app can only load its own JNI libraries along with the public libs.
-static constexpr const char* kClassloaderNamespaceName = "classloader-namespace";
-// Same thing for vendor APKs.
-static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace";
-
-// (http://b/27588281) This is a workaround for apps using custom classloaders and calling
-// System.load() with an absolute path which is outside of the classloader library search path.
-// This list includes all directories app is allowed to access this way.
-static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
-
-static constexpr const char* kApexPath = "/apex/";
-
-#if defined(__LP64__)
-static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib64";
-static constexpr const char* kVendorLibPath = "/vendor/lib64";
-static constexpr const char* kProductLibPath = "/product/lib64:/system/product/lib64";
-#else
-static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib";
-static constexpr const char* kVendorLibPath = "/vendor/lib";
-static constexpr const char* kProductLibPath = "/product/lib:/system/product/lib";
-#endif
-
-static const std::regex kVendorDexPathRegex("(^|:)/vendor/");
-static const std::regex kProductDexPathRegex("(^|:)(/system)?/product/");
-
-// Define origin of APK if it is from vendor partition or product partition
-typedef enum {
-  APK_ORIGIN_DEFAULT = 0,
-  APK_ORIGIN_VENDOR = 1,
-  APK_ORIGIN_PRODUCT = 2,
-} ApkOrigin;
-
-static bool is_debuggable() {
-  bool debuggable = false;
-#ifdef __BIONIC__
-  debuggable = android::base::GetBoolProperty("ro.debuggable", false);
-#endif
-  return debuggable;
-}
-
-static std::string vndk_version_str() {
-#ifdef __BIONIC__
-  std::string version = android::base::GetProperty("ro.vndk.version", "");
-  if (version != "" && version != "current") {
-    return "." + version;
-  }
-#endif
-  return "";
-}
-
-static void insert_vndk_version_str(std::string* file_name) {
-  CHECK(file_name != nullptr);
-  size_t insert_pos = file_name->find_last_of(".");
-  if (insert_pos == std::string::npos) {
-    insert_pos = file_name->length();
-  }
-  file_name->insert(insert_pos, vndk_version_str());
-}
-
-static const std::function<bool(const std::string&, std::string*)> always_true =
-    [](const std::string&, std::string*) { return true; };
-
-class LibraryNamespaces {
- public:
-  LibraryNamespaces() : initialized_(false) { }
-
-  NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
-                                bool is_shared, jstring dex_path, jstring java_library_path,
-                                jstring java_permitted_path, std::string* error_msg) {
-    std::string library_path; // empty string by default.
-
-    if (java_library_path != nullptr) {
-      ScopedUtfChars library_path_utf_chars(env, java_library_path);
-      library_path = library_path_utf_chars.c_str();
-    }
-
-    ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path);
-
-    // (http://b/27588281) This is a workaround for apps using custom
-    // classloaders and calling System.load() with an absolute path which
-    // is outside of the classloader library search path.
-    //
-    // This part effectively allows such a classloader to access anything
-    // under /data and /mnt/expand
-    std::string permitted_path = kWhitelistedDirectories;
-
-    if (java_permitted_path != nullptr) {
-      ScopedUtfChars path(env, java_permitted_path);
-      if (path.c_str() != nullptr && path.size() > 0) {
-        permitted_path = permitted_path + ":" + path.c_str();
-      }
-    }
-
-    // Initialize the anonymous namespace with the first non-empty library path.
-    if (!library_path.empty() && !initialized_ &&
-        !InitPublicNamespace(library_path.c_str(), error_msg)) {
-      return nullptr;
-    }
-
-    bool found = FindNamespaceByClassLoader(env, class_loader);
-
-    LOG_ALWAYS_FATAL_IF(found,
-                        "There is already a namespace associated with this classloader");
-
-    uint64_t namespace_type = ANDROID_NAMESPACE_TYPE_ISOLATED;
-    if (is_shared) {
-      namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
-    }
-
-    if (target_sdk_version < 24) {
-      namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED;
-    }
-
-    NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
-
-    bool is_native_bridge = false;
-
-    if (parent_ns != nullptr) {
-      is_native_bridge = !parent_ns->is_android_namespace();
-    } else if (!library_path.empty()) {
-      is_native_bridge = NativeBridgeIsPathSupported(library_path.c_str());
-    }
-
-    std::string system_exposed_libraries = system_public_libraries_;
-    const char* namespace_name = kClassloaderNamespaceName;
-    android_namespace_t* vndk_ns = nullptr;
-    if ((apk_origin == APK_ORIGIN_VENDOR ||
-         (apk_origin == APK_ORIGIN_PRODUCT && target_sdk_version > 29)) &&
-        !is_shared) {
-      LOG_FATAL_IF(is_native_bridge,
-                   "Unbundled vendor / product apk must not use translated architecture");
-
-      // For vendor / product apks, give access to the vendor / product lib even though
-      // they are treated as unbundled; the libs and apks are still bundled
-      // together in the vendor / product partition.
-      const char* origin_partition;
-      const char* origin_lib_path;
-
-      switch (apk_origin) {
-        case APK_ORIGIN_VENDOR:
-          origin_partition = "vendor";
-          origin_lib_path = kVendorLibPath;
-          break;
-        case APK_ORIGIN_PRODUCT:
-          origin_partition = "product";
-          origin_lib_path = kProductLibPath;
-          break;
-        default:
-          origin_partition = "unknown";
-          origin_lib_path = "";
-      }
-
-      LOG_FATAL_IF(is_native_bridge, "Unbundled %s apk must not use translated architecture",
-                   origin_partition);
-
-      library_path = library_path + ":" + origin_lib_path;
-      permitted_path = permitted_path + ":" + origin_lib_path;
-
-      // Also give access to LLNDK libraries since they are available to vendors
-      system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str();
-
-      // Give access to VNDK-SP libraries from the 'vndk' namespace.
-      vndk_ns = android_get_exported_namespace(kVndkNamespaceName);
-      if (vndk_ns == nullptr) {
-        ALOGW("Cannot find \"%s\" namespace for %s apks", kVndkNamespaceName, origin_partition);
-      }
-
-      // Different name is useful for debugging
-      namespace_name = kVendorClassloaderNamespaceName;
-      ALOGD("classloader namespace configured for unbundled %s apk. library_path=%s",
-            origin_partition, library_path.c_str());
-    } else {
-      // oem and product public libraries are NOT available to vendor apks, otherwise it
-      // would be system->vendor violation.
-      if (!oem_public_libraries_.empty()) {
-        system_exposed_libraries = system_exposed_libraries + ':' + oem_public_libraries_;
-      }
-      if (!product_public_libraries_.empty()) {
-        system_exposed_libraries = system_exposed_libraries + ':' + product_public_libraries_;
-      }
-    }
-
-    std::string runtime_exposed_libraries = base::Join(kRuntimePublicLibraries, ":");
-
-    NativeLoaderNamespace native_loader_ns;
-    if (!is_native_bridge) {
-      android_namespace_t* android_parent_ns;
-      if (parent_ns != nullptr) {
-        android_parent_ns = parent_ns->get_android_ns();
-      } else {
-        // Fall back to the platform namespace if no parent is found. It is
-        // called "default" for binaries in /system and "platform" for those in
-        // the Runtime APEX. Try "platform" first since "default" always exists.
-        android_parent_ns = android_get_exported_namespace(kPlatformNamespaceName);
-        if (android_parent_ns == nullptr) {
-          android_parent_ns = android_get_exported_namespace(kDefaultNamespaceName);
-        }
-      }
-
-      android_namespace_t* ns = android_create_namespace(namespace_name,
-                                                         nullptr,
-                                                         library_path.c_str(),
-                                                         namespace_type,
-                                                         permitted_path.c_str(),
-                                                         android_parent_ns);
-      if (ns == nullptr) {
-        *error_msg = dlerror();
-        return nullptr;
-      }
-
-      // Note that when vendor_ns is not configured this function will return nullptr
-      // and it will result in linking vendor_public_libraries_ to the default namespace
-      // which is expected behavior in this case.
-      android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
-
-      android_namespace_t* runtime_ns = android_get_exported_namespace(kRuntimeNamespaceName);
-
-      if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) {
-        *error_msg = dlerror();
-        return nullptr;
-      }
-
-      // Runtime apex does not exist in host, and under certain build conditions.
-      if (runtime_ns != nullptr) {
-        if (!android_link_namespaces(ns, runtime_ns, runtime_exposed_libraries.c_str())) {
-          *error_msg = dlerror();
-          return nullptr;
-        }
-      }
-
-      if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) {
-        // vendor apks are allowed to use VNDK-SP libraries.
-        if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) {
-          *error_msg = dlerror();
-          return nullptr;
-        }
-      }
-
-      if (!vendor_public_libraries_.empty()) {
-        if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
-          *error_msg = dlerror();
-          return nullptr;
-        }
-      }
-
-      native_loader_ns = NativeLoaderNamespace(ns);
-    } else {
-      native_bridge_namespace_t* native_bridge_parent_namespace;
-      if (parent_ns != nullptr) {
-        native_bridge_parent_namespace = parent_ns->get_native_bridge_ns();
-      } else {
-        native_bridge_parent_namespace = NativeBridgeGetExportedNamespace(kPlatformNamespaceName);
-        if (native_bridge_parent_namespace == nullptr) {
-          native_bridge_parent_namespace = NativeBridgeGetExportedNamespace(kDefaultNamespaceName);
-        }
-      }
-
-      native_bridge_namespace_t* ns = NativeBridgeCreateNamespace(namespace_name,
-                                                                  nullptr,
-                                                                  library_path.c_str(),
-                                                                  namespace_type,
-                                                                  permitted_path.c_str(),
-                                                                  native_bridge_parent_namespace);
-      if (ns == nullptr) {
-        *error_msg = NativeBridgeGetError();
-        return nullptr;
-      }
-
-      native_bridge_namespace_t* vendor_ns = NativeBridgeGetExportedNamespace(kVendorNamespaceName);
-      native_bridge_namespace_t* runtime_ns =
-          NativeBridgeGetExportedNamespace(kRuntimeNamespaceName);
-
-      if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) {
-        *error_msg = NativeBridgeGetError();
-        return nullptr;
-      }
-
-      // Runtime apex does not exist in host, and under certain build conditions.
-      if (runtime_ns != nullptr) {
-        if (!NativeBridgeLinkNamespaces(ns, runtime_ns, runtime_exposed_libraries.c_str())) {
-          *error_msg = NativeBridgeGetError();
-          return nullptr;
-        }
-      }
-      if (!vendor_public_libraries_.empty()) {
-        if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
-          *error_msg = NativeBridgeGetError();
-          return nullptr;
-        }
-      }
-
-      native_loader_ns = NativeLoaderNamespace(ns);
-    }
-
-    namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), native_loader_ns));
-
-    return &(namespaces_.back().second);
-  }
-
-  NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
-    auto it = std::find_if(namespaces_.begin(), namespaces_.end(),
-                [&](const std::pair<jweak, NativeLoaderNamespace>& value) {
-                  return env->IsSameObject(value.first, class_loader);
-                });
-    if (it != namespaces_.end()) {
-      return &it->second;
-    }
-
-    return nullptr;
-  }
-
-  void Initialize() {
-    // Once public namespace is initialized there is no
-    // point in running this code - it will have no effect
-    // on the current list of public libraries.
-    if (initialized_) {
-      return;
-    }
-
-    std::vector<std::string> sonames;
-    const char* android_root_env = getenv("ANDROID_ROOT");
-    std::string root_dir = android_root_env != nullptr ? android_root_env : "/system";
-    std::string public_native_libraries_system_config =
-            root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot;
-    std::string llndk_native_libraries_system_config =
-            root_dir + kLlndkNativeLibrariesSystemConfigPathFromRoot;
-    std::string vndksp_native_libraries_system_config =
-            root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot;
-
-    std::string product_public_native_libraries_dir = "/product/etc";
-
-    std::string error_msg;
-    LOG_ALWAYS_FATAL_IF(
-        !ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg),
-        "Error reading public native library list from \"%s\": %s",
-        public_native_libraries_system_config.c_str(), error_msg.c_str());
-
-    // For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment
-    // variable to add libraries to the list. This is intended for platform tests only.
-    if (is_debuggable()) {
-      const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");
-      if (additional_libs != nullptr && additional_libs[0] != '\0') {
-        std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":");
-        std::copy(additional_libs_vector.begin(), additional_libs_vector.end(),
-                  std::back_inserter(sonames));
-      }
-    }
-
-    // Remove the public libs in the runtime namespace.
-    // These libs are listed in public.android.txt, but we don't want the rest of android
-    // in default namespace to dlopen the libs.
-    // For example, libicuuc.so is exposed to classloader namespace from runtime namespace.
-    // Unfortunately, it does not have stable C symbols, and default namespace should only use
-    // stable symbols in libandroidicu.so. http://b/120786417
-    removePublicLibsIfExistsInRuntimeApex(sonames);
-
-    // android_init_namespaces() expects all the public libraries
-    // to be loaded so that they can be found by soname alone.
-    //
-    // TODO(dimitry): this is a bit misleading since we do not know
-    // if the vendor public library is going to be opened from /vendor/lib
-    // we might as well end up loading them from /system/lib or /product/lib
-    // For now we rely on CTS test to catch things like this but
-    // it should probably be addressed in the future.
-    for (const auto& soname : sonames) {
-      LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
-                          "Error preloading public library %s: %s", soname.c_str(), dlerror());
-    }
-
-    system_public_libraries_ = base::Join(sonames, ':');
-
-    // read /system/etc/public.libraries-<companyname>.txt which contain partner defined
-    // system libs that are exposed to apps. The libs in the txt files must be
-    // named as lib<name>.<companyname>.so.
-    sonames.clear();
-    ReadExtensionLibraries(base::Dirname(public_native_libraries_system_config).c_str(), &sonames);
-    oem_public_libraries_ = base::Join(sonames, ':');
-
-    // read /product/etc/public.libraries-<companyname>.txt which contain partner defined
-    // product libs that are exposed to apps.
-    sonames.clear();
-    ReadExtensionLibraries(product_public_native_libraries_dir.c_str(), &sonames);
-    product_public_libraries_ = base::Join(sonames, ':');
-
-    // Insert VNDK version to llndk and vndksp config file names.
-    insert_vndk_version_str(&llndk_native_libraries_system_config);
-    insert_vndk_version_str(&vndksp_native_libraries_system_config);
-
-    sonames.clear();
-    ReadConfig(llndk_native_libraries_system_config, &sonames, always_true);
-    system_llndk_libraries_ = base::Join(sonames, ':');
-
-    sonames.clear();
-    ReadConfig(vndksp_native_libraries_system_config, &sonames, always_true);
-    system_vndksp_libraries_ = base::Join(sonames, ':');
-
-    sonames.clear();
-    // This file is optional, quietly ignore if the file does not exist.
-    ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames, always_true, nullptr);
-
-    vendor_public_libraries_ = base::Join(sonames, ':');
-  }
-
-  void Reset() { namespaces_.clear(); }
-
- private:
-  void ReadExtensionLibraries(const char* dirname, std::vector<std::string>* sonames) {
-    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname), closedir);
-    if (dir != nullptr) {
-      // Failing to opening the dir is not an error, which can happen in
-      // webview_zygote.
-      while (struct dirent* ent = readdir(dir.get())) {
-        if (ent->d_type != DT_REG && ent->d_type != DT_LNK) {
-          continue;
-        }
-        const std::string filename(ent->d_name);
-        if (android::base::StartsWith(filename, kPublicNativeLibrariesExtensionConfigPrefix) &&
-            android::base::EndsWith(filename, kPublicNativeLibrariesExtensionConfigSuffix)) {
-          const size_t start = kPublicNativeLibrariesExtensionConfigPrefixLen;
-          const size_t end = filename.size() - kPublicNativeLibrariesExtensionConfigSuffixLen;
-          const std::string company_name = filename.substr(start, end - start);
-          const std::string config_file_path = dirname + "/"s + filename;
-          LOG_ALWAYS_FATAL_IF(
-              company_name.empty(),
-              "Error extracting company name from public native library list file path \"%s\"",
-              config_file_path.c_str());
-
-          std::string error_msg;
-
-          LOG_ALWAYS_FATAL_IF(
-              !ReadConfig(
-                  config_file_path, sonames,
-                  [&company_name](const std::string& soname, std::string* error_msg) {
-                    if (android::base::StartsWith(soname, "lib") &&
-                        android::base::EndsWith(soname, "." + company_name + ".so")) {
-                      return true;
-                    } else {
-                      *error_msg = "Library name \"" + soname +
-                                   "\" does not end with the company name: " + company_name + ".";
-                      return false;
-                    }
-                  },
-                  &error_msg),
-              "Error reading public native library list from \"%s\": %s", config_file_path.c_str(),
-              error_msg.c_str());
-        }
-      }
-    }
-  }
-
-  /**
-   * Remove the public libs in runtime namespace
-   */
-  void removePublicLibsIfExistsInRuntimeApex(std::vector<std::string>& sonames) {
-    for (const std::string& lib_name : kRuntimePublicLibraries) {
-      std::string path(kRuntimeApexLibPath);
-      path.append("/").append(lib_name);
-
-      struct stat s;
-      // Do nothing if the path in /apex does not exist.
-      // Runtime APEX must be mounted since libnativeloader is in the same APEX
-      if (stat(path.c_str(), &s) != 0) {
-        continue;
-      }
-
-      auto it = std::find(sonames.begin(), sonames.end(), lib_name);
-      if (it != sonames.end()) {
-        sonames.erase(it);
-      }
-    }
-  }
-
-  bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames,
-                  const std::function<bool(const std::string& /* soname */,
-                                           std::string* /* error_msg */)>& check_soname,
-                  std::string* error_msg = nullptr) {
-    // Read list of public native libraries from the config file.
-    std::string file_content;
-    if(!base::ReadFileToString(configFile, &file_content)) {
-      if (error_msg) *error_msg = strerror(errno);
-      return false;
-    }
-
-    std::vector<std::string> lines = base::Split(file_content, "\n");
-
-    for (auto& line : lines) {
-      auto trimmed_line = base::Trim(line);
-      if (trimmed_line[0] == '#' || trimmed_line.empty()) {
-        continue;
-      }
-      size_t space_pos = trimmed_line.rfind(' ');
-      if (space_pos != std::string::npos) {
-        std::string type = trimmed_line.substr(space_pos + 1);
-        if (type != "32" && type != "64") {
-          if (error_msg) *error_msg = "Malformed line: " + line;
-          return false;
-        }
-#if defined(__LP64__)
-        // Skip 32 bit public library.
-        if (type == "32") {
-          continue;
-        }
-#else
-        // Skip 64 bit public library.
-        if (type == "64") {
-          continue;
-        }
-#endif
-        trimmed_line.resize(space_pos);
-      }
-
-      if (check_soname(trimmed_line, error_msg)) {
-        sonames->push_back(trimmed_line);
-      } else {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
-  bool InitPublicNamespace(const char* library_path, std::string* error_msg) {
-    // Ask native bride if this apps library path should be handled by it
-    bool is_native_bridge = NativeBridgeIsPathSupported(library_path);
-
-    // (http://b/25844435) - Some apps call dlopen from generated code (mono jited
-    // code is one example) unknown to linker in which  case linker uses anonymous
-    // namespace. The second argument specifies the search path for the anonymous
-    // namespace which is the library_path of the classloader.
-    initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(),
-                                                    is_native_bridge ? nullptr : library_path);
-    if (!initialized_) {
-      *error_msg = dlerror();
-      return false;
-    }
-
-    // and now initialize native bridge namespaces if necessary.
-    if (NativeBridgeInitialized()) {
-      initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(),
-                                                        is_native_bridge ? library_path : nullptr);
-      if (!initialized_) {
-        *error_msg = NativeBridgeGetError();
-      }
-    }
-
-    return initialized_;
-  }
-
-  jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
-    jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
-    jmethodID get_parent = env->GetMethodID(class_loader_class,
-                                            "getParent",
-                                            "()Ljava/lang/ClassLoader;");
-
-    return env->CallObjectMethod(class_loader, get_parent);
-  }
-
-  NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
-    jobject parent_class_loader = GetParentClassLoader(env, class_loader);
-
-    while (parent_class_loader != nullptr) {
-      NativeLoaderNamespace* ns;
-      if ((ns = FindNamespaceByClassLoader(env, parent_class_loader)) != nullptr) {
-        return ns;
-      }
-
-      parent_class_loader = GetParentClassLoader(env, parent_class_loader);
-    }
-
-    return nullptr;
-  }
-
-  ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) {
-    ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;
-
-    if (dex_path != nullptr) {
-      ScopedUtfChars dex_path_utf_chars(env, dex_path);
-
-      if (std::regex_search(dex_path_utf_chars.c_str(), kVendorDexPathRegex)) {
-        apk_origin = APK_ORIGIN_VENDOR;
-      }
-
-      if (std::regex_search(dex_path_utf_chars.c_str(), kProductDexPathRegex)) {
-        LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
-                            "Dex path contains both vendor and product partition : %s",
-                            dex_path_utf_chars.c_str());
-
-        apk_origin = APK_ORIGIN_PRODUCT;
-      }
-    }
-
-    return apk_origin;
-  }
-
-  bool initialized_;
-  std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
-  std::string system_public_libraries_;
-  std::string vendor_public_libraries_;
-  std::string oem_public_libraries_;
-  std::string product_public_libraries_;
-  std::string system_llndk_libraries_;
-  std::string system_vndksp_libraries_;
-
-  DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
-};
-
-static std::mutex g_namespaces_mutex;
-static LibraryNamespaces* g_namespaces = new LibraryNamespaces;
-#endif
-
-void InitializeNativeLoader() {
-#if defined(__ANDROID__)
-  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  g_namespaces->Initialize();
-#endif
-}
-
-void ResetNativeLoader() {
-#if defined(__ANDROID__)
-  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  g_namespaces->Reset();
-#endif
-}
-
-jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
-                                   bool is_shared, jstring dex_path, jstring library_path,
-                                   jstring permitted_path) {
-#if defined(__ANDROID__)
-  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-
-  std::string error_msg;
-  bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
-                                      library_path, permitted_path, &error_msg) != nullptr;
-  if (!success) {
-    return env->NewStringUTF(error_msg.c_str());
-  }
-#else
-  UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
-#endif
-  return nullptr;
-}
-
-#if defined(__ANDROID__)
-static android_namespace_t* FindExportedNamespace(const char* caller_location) {
-  std::string location = caller_location;
-  // Lots of implicit assumptions here: we expect `caller_location` to be of the form:
-  // /apex/com.android...modulename/...
-  //
-  // And we extract from it 'modulename', which is the name of the linker namespace.
-  if (android::base::StartsWith(location, kApexPath)) {
-    size_t slash_index = location.find_first_of('/', strlen(kApexPath));
-    LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
-                        "Error finding namespace of apex: no slash in path %s", caller_location);
-    size_t dot_index = location.find_last_of('.', slash_index);
-    LOG_ALWAYS_FATAL_IF((dot_index == std::string::npos),
-                        "Error finding namespace of apex: no dot in apex name %s", caller_location);
-    std::string name = location.substr(dot_index + 1, slash_index - dot_index - 1);
-    android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
-    LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
-                        "Error finding namespace of apex: no namespace called %s", name.c_str());
-    return boot_namespace;
-  }
-  return nullptr;
-}
-#endif
-
-void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
-                        jobject class_loader, const char* caller_location, jstring library_path,
-                        bool* needs_native_bridge, char** error_msg) {
-#if defined(__ANDROID__)
-  UNUSED(target_sdk_version);
-  if (class_loader == nullptr) {
-    *needs_native_bridge = false;
-    if (caller_location != nullptr) {
-      android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
-      if (boot_namespace != nullptr) {
-        const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE,
-            .library_namespace = boot_namespace,
-        };
-        void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
-        if (handle == nullptr) {
-          *error_msg = strdup(dlerror());
-        }
-        return handle;
-      }
-    }
-    void* handle = dlopen(path, RTLD_NOW);
-    if (handle == nullptr) {
-      *error_msg = strdup(dlerror());
-    }
-    return handle;
-  }
-
-  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  NativeLoaderNamespace* ns;
-
-  if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
-    // This is the case where the classloader was not created by ApplicationLoaders
-    // In this case we create an isolated not-shared namespace for it.
-    std::string create_error_msg;
-    if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
-                                   nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
-      *error_msg = strdup(create_error_msg.c_str());
-      return nullptr;
-    }
-  }
-
-  return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
-#else
-  UNUSED(env, target_sdk_version, class_loader, caller_location);
-
-  // Do some best effort to emulate library-path support. It will not
-  // work for dependencies.
-  //
-  // Note: null has a special meaning and must be preserved.
-  std::string c_library_path;  // Empty string by default.
-  if (library_path != nullptr && path != nullptr && path[0] != '/') {
-    ScopedUtfChars library_path_utf_chars(env, library_path);
-    c_library_path = library_path_utf_chars.c_str();
-  }
-
-  std::vector<std::string> library_paths = base::Split(c_library_path, ":");
-
-  for (const std::string& lib_path : library_paths) {
-    *needs_native_bridge = false;
-    const char* path_arg;
-    std::string complete_path;
-    if (path == nullptr) {
-      // Preserve null.
-      path_arg = nullptr;
-    } else {
-      complete_path = lib_path;
-      if (!complete_path.empty()) {
-        complete_path.append("/");
-      }
-      complete_path.append(path);
-      path_arg = complete_path.c_str();
-    }
-    void* handle = dlopen(path_arg, RTLD_NOW);
-    if (handle != nullptr) {
-      return handle;
-    }
-    if (NativeBridgeIsSupported(path_arg)) {
-      *needs_native_bridge = true;
-      handle = NativeBridgeLoadLibrary(path_arg, RTLD_NOW);
-      if (handle != nullptr) {
-        return handle;
-      }
-      *error_msg = strdup(NativeBridgeGetError());
-    } else {
-      *error_msg = strdup(dlerror());
-    }
-  }
-  return nullptr;
-#endif
-}
-
-bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
-  bool success;
-  if (needs_native_bridge) {
-    success = (NativeBridgeUnloadLibrary(handle) == 0);
-    if (!success) {
-      *error_msg = strdup(NativeBridgeGetError());
-    }
-  } else {
-    success = (dlclose(handle) == 0);
-    if (!success) {
-      *error_msg = strdup(dlerror());
-    }
-  }
-
-  return success;
-}
-
-void NativeLoaderFreeErrorMessage(char* msg) {
-  // The error messages get allocated through strdup, so we must call free on them.
-  free(msg);
-}
-
-#if defined(__ANDROID__)
-void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
-                                   bool* needs_native_bridge, char** error_msg) {
-  if (ns->is_android_namespace()) {
-    android_dlextinfo extinfo;
-    extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
-    extinfo.library_namespace = ns->get_android_ns();
-
-    void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
-    if (handle == nullptr) {
-      *error_msg = strdup(dlerror());
-    }
-    *needs_native_bridge = false;
-    return handle;
-  } else {
-    void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns());
-    if (handle == nullptr) {
-      *error_msg = strdup(NativeBridgeGetError());
-    }
-    *needs_native_bridge = true;
-    return handle;
-  }
-}
-
-// native_bridge_namespaces are not supported for callers of this function.
-// This function will return nullptr in the case when application is running
-// on native bridge.
-android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
-  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader);
-  if (ns != nullptr) {
-    return ns->is_android_namespace() ? ns->get_android_ns() : nullptr;
-  }
-
-  return nullptr;
-}
-NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
-  std::lock_guard<std::mutex> guard(g_namespaces_mutex);
-  return g_namespaces->FindNamespaceByClassLoader(env, class_loader);
-}
-#endif
-
-}; //  android namespace
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
deleted file mode 100644
index 2eb1203..0000000
--- a/libnativeloader/native_loader_lazy.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 "nativeloader/native_loader.h"
-#define LOG_TAG "nativeloader"
-
-#include <dlfcn.h>
-#include <errno.h>
-#include <string.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace {
-
-void* GetLibHandle() {
-  static void* handle = dlopen("libnativeloader.so", RTLD_NOW);
-  LOG_FATAL_IF(handle == nullptr, "Failed to load libnativeloader.so: %s", dlerror());
-  return handle;
-}
-
-template <typename FuncPtr>
-FuncPtr GetFuncPtr(const char* function_name) {
-  auto f = reinterpret_cast<FuncPtr>(dlsym(GetLibHandle(), function_name));
-  LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror());
-  return f;
-}
-
-#define GET_FUNC_PTR(name) GetFuncPtr<decltype(&name)>(#name)
-
-}  // namespace
-
-void InitializeNativeLoader() {
-  static auto f = GET_FUNC_PTR(InitializeNativeLoader);
-  return f();
-}
-
-jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
-                                   bool is_shared, jstring dex_path, jstring library_path,
-                                   jstring permitted_path) {
-  static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
-  return f(env, target_sdk_version, class_loader, is_shared, dex_path, library_path,
-           permitted_path);
-}
-
-void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
-                        jobject class_loader, const char* caller_location, jstring library_path,
-                        bool* needs_native_bridge, char** error_msg) {
-  static auto f = GET_FUNC_PTR(OpenNativeLibrary);
-  return f(env, target_sdk_version, path, class_loader, caller_location, library_path,
-           needs_native_bridge, error_msg);
-}
-
-bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
-  static auto f = GET_FUNC_PTR(CloseNativeLibrary);
-  return f(handle, needs_native_bridge, error_msg);
-}
-
-void NativeLoaderFreeErrorMessage(char* msg) {
-  static auto f = GET_FUNC_PTR(NativeLoaderFreeErrorMessage);
-  return f(msg);
-}
-
-struct android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
-  static auto f = GET_FUNC_PTR(FindNamespaceByClassLoader);
-  return f(env, class_loader);
-}
-
-struct NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(JNIEnv* env,
-                                                                     jobject class_loader) {
-  static auto f = GET_FUNC_PTR(FindNativeLoaderNamespaceByClassLoader);
-  return f(env, class_loader);
-}
-
-void* OpenNativeLibraryInNamespace(struct NativeLoaderNamespace* ns, const char* path,
-                                   bool* needs_native_bridge, char** error_msg) {
-  static auto f = GET_FUNC_PTR(OpenNativeLibraryInNamespace);
-  return f(ns, path, needs_native_bridge, error_msg);
-}
-
-void ResetNativeLoader() {
-  static auto f = GET_FUNC_PTR(ResetNativeLoader);
-  return f();
-}
-
-#undef GET_FUNC_PTR
-
-}  // namespace android
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
deleted file mode 100644
index 4d5c53d..0000000
--- a/libnativeloader/test/Android.bp
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright (C) 2017 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_library {
-    name: "libfoo.oem1",
-    srcs: ["test.cpp"],
-    cflags: ["-DLIBNAME=\"libfoo.oem1.so\""],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_library {
-    name: "libbar.oem1",
-    srcs: ["test.cpp"],
-    cflags: ["-DLIBNAME=\"libbar.oem1.so\""],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_library {
-    name: "libfoo.oem2",
-    srcs: ["test.cpp"],
-    cflags: ["-DLIBNAME=\"libfoo.oem2.so\""],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_library {
-    name: "libbar.oem2",
-    srcs: ["test.cpp"],
-    cflags: ["-DLIBNAME=\"libbar.oem2.so\""],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_library {
-    name: "libfoo.product1",
-    srcs: ["test.cpp"],
-    cflags: ["-DLIBNAME=\"libfoo.product1.so\""],
-    product_specific: true,
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-cc_library {
-    name: "libbar.product1",
-    srcs: ["test.cpp"],
-    cflags: ["-DLIBNAME=\"libbar.product1.so\""],
-    product_specific: true,
-    shared_libs: [
-        "libbase",
-    ],
-}
-
-// Build the test for the C API.
-cc_test {
-    name: "libnativeloader-api-tests",
-    host_supported: true,
-    test_per_src: true,
-    srcs: [
-        "api_test.c",
-    ],
-    header_libs: ["libnativeloader-headers"],
-}
diff --git a/libnativeloader/test/Android.mk b/libnativeloader/test/Android.mk
deleted file mode 100644
index 65e7b09..0000000
--- a/libnativeloader/test/Android.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (C) 2017 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.
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := public.libraries-oem1.txt
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := public.libraries-oem2.txt
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := public.libraries-product1.txt
-LOCAL_SRC_FILES:= $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := oemlibrarytest-system
-LOCAL_MODULE_TAGS := tests
-LOCAL_MANIFEST_FILE := system/AndroidManifest.xml
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_MODULE_PATH := $(TARGET_OUT_APPS)
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := oemlibrarytest-vendor
-LOCAL_MODULE_TAGS := tests
-LOCAL_MANIFEST_FILE := vendor/AndroidManifest.xml
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := current
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_APPS)
-include $(BUILD_PACKAGE)
diff --git a/libnativeloader/test/public.libraries-oem1.txt b/libnativeloader/test/public.libraries-oem1.txt
deleted file mode 100644
index f9433e2..0000000
--- a/libnativeloader/test/public.libraries-oem1.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-libfoo.oem1.so
-libbar.oem1.so
diff --git a/libnativeloader/test/public.libraries-oem2.txt b/libnativeloader/test/public.libraries-oem2.txt
deleted file mode 100644
index de6bdb0..0000000
--- a/libnativeloader/test/public.libraries-oem2.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-libfoo.oem2.so
-libbar.oem2.so
diff --git a/libnativeloader/test/public.libraries-product1.txt b/libnativeloader/test/public.libraries-product1.txt
deleted file mode 100644
index 358154c..0000000
--- a/libnativeloader/test/public.libraries-product1.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-libfoo.product1.so
-libbar.product1.so
diff --git a/libnativeloader/test/runtest.sh b/libnativeloader/test/runtest.sh
deleted file mode 100755
index 40beb5b..0000000
--- a/libnativeloader/test/runtest.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-adb root
-adb remount
-adb sync
-adb shell stop
-adb shell start
-sleep 5 # wait until device reboots
-adb logcat -c;
-adb shell am start -n android.test.app.system/android.test.app.TestActivity
-adb shell am start -n android.test.app.vendor/android.test.app.TestActivity
-adb logcat | grep android.test.app
diff --git a/libnativeloader/test/src/android/test/app/TestActivity.java b/libnativeloader/test/src/android/test/app/TestActivity.java
deleted file mode 100644
index a7a455d..0000000
--- a/libnativeloader/test/src/android/test/app/TestActivity.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- */
-
-package android.test.app;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-public class TestActivity extends Activity {
-
-    @Override
-    public void onCreate(Bundle icicle) {
-         super.onCreate(icicle);
-         tryLoadingLib("foo.oem1");
-         tryLoadingLib("bar.oem1");
-         tryLoadingLib("foo.oem2");
-         tryLoadingLib("bar.oem2");
-         tryLoadingLib("foo.product1");
-         tryLoadingLib("bar.product1");
-    }
-
-    private void tryLoadingLib(String name) {
-        try {
-            System.loadLibrary(name);
-            Log.d(getPackageName(), "library " + name + " is successfully loaded");
-        } catch (UnsatisfiedLinkError e) {
-            Log.d(getPackageName(), "failed to load libarary " + name, e);
-        }
-    }
-}
diff --git a/libnativeloader/test/system/AndroidManifest.xml b/libnativeloader/test/system/AndroidManifest.xml
deleted file mode 100644
index c304889..0000000
--- a/libnativeloader/test/system/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.test.app.system">
-
-    <application>
-        <activity android:name="android.test.app.TestActivity" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-
-</manifest>
-
diff --git a/libnativeloader/test/test.cpp b/libnativeloader/test/test.cpp
deleted file mode 100644
index b166928..0000000
--- a/libnativeloader/test/test.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 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 "oemlib"
-#include <android-base/logging.h>
-
-static __attribute__((constructor)) void test_lib_init() {
-  LOG(DEBUG) << LIBNAME << " loaded";
-}
diff --git a/libnativeloader/test/vendor/AndroidManifest.xml b/libnativeloader/test/vendor/AndroidManifest.xml
deleted file mode 100644
index c4c1a9c..0000000
--- a/libnativeloader/test/vendor/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.test.app.vendor">
-
-    <application>
-        <activity android:name="android.test.app.TestActivity" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-    </application>
-
-</manifest>
-
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index a098d59..8212eba 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -113,6 +113,10 @@
     if (ret == 0) {
         memcpy(ss, ai->ai_addr, ai->ai_addrlen);
         freeaddrinfo(ai);
+    } else {
+        // Getaddrinfo has its own error codes. Convert to negative errno.
+        // There, the only thing that can reasonably happen is that the passed-in string is invalid.
+        ret = (ret == EAI_SYSTEM) ? -errno : -EINVAL;
     }
 
     return ret;
@@ -263,19 +267,13 @@
     struct {
         struct nlmsghdr n;
         struct ifaddrmsg r;
-        // Allow for IPv6 address, headers, IPv4 broadcast addr and padding.
-        char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
-                     NLMSG_ALIGN(sizeof(struct rtattr)) +
-                     NLMSG_ALIGN(INET6_ADDRLEN) +
-                     NLMSG_ALIGN(sizeof(struct rtattr)) +
-                     NLMSG_ALIGN(INET_ADDRLEN)];
+        // Allow for IPv4 or IPv6 address, headers, IPv4 broadcast address and padding.
+        char attrbuf[NLMSG_ALIGN(sizeof(struct rtattr)) + NLMSG_ALIGN(INET6_ADDRLEN) +
+                     NLMSG_ALIGN(sizeof(struct rtattr)) + NLMSG_ALIGN(INET_ADDRLEN)];
     } req;
     struct rtattr *rta;
     struct nlmsghdr *nh;
     struct nlmsgerr *err;
-    char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
-             NLMSG_ALIGN(sizeof(struct nlmsgerr)) +
-             NLMSG_ALIGN(sizeof(struct nlmsghdr))];
 
     // Get interface ID.
     ifindex = if_nametoindex(name);
@@ -344,6 +342,7 @@
         return -saved_errno;
     }
 
+    char buf[NLMSG_ALIGN(sizeof(struct nlmsgerr)) + sizeof(req)];
     len = recv(s, buf, sizeof(buf), 0);
     saved_errno = errno;
     close(s);
@@ -362,10 +361,12 @@
     return err->error;
 }
 
+// Returns zero on success and negative errno on failure.
 int ifc_add_address(const char *name, const char *address, int prefixlen) {
     return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen);
 }
 
+// Returns zero on success and negative errno on failure.
 int ifc_del_address(const char *name, const char * address, int prefixlen) {
     return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen);
 }
diff --git a/libnativeloader/.clang-format b/libpackagelistparser/.clang-format
similarity index 100%
rename from libnativeloader/.clang-format
rename to libpackagelistparser/.clang-format
diff --git a/libpackagelistparser/Android.bp b/libpackagelistparser/Android.bp
index c38594a..b56dcdb 100644
--- a/libpackagelistparser/Android.bp
+++ b/libpackagelistparser/Android.bp
@@ -1,12 +1,7 @@
 cc_library {
-
     name: "libpackagelistparser",
     recovery_available: true,
-    srcs: ["packagelistparser.c"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
+    srcs: ["packagelistparser.cpp"],
     shared_libs: ["liblog"],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
@@ -15,3 +10,14 @@
         misc_undefined: ["integer"],
     },
 }
+
+cc_test {
+    name: "libpackagelistparser_test",
+    srcs: ["packagelistparser_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "libpackagelistparser",
+    ],
+    test_suites: ["device-tests"],
+    require_root: true,
+}
diff --git a/libpackagelistparser/include/packagelistparser/packagelistparser.h b/libpackagelistparser/include/packagelistparser/packagelistparser.h
index 3cb6b9a..e89cb54 100644
--- a/libpackagelistparser/include/packagelistparser/packagelistparser.h
+++ b/libpackagelistparser/include/packagelistparser/packagelistparser.h
@@ -1,94 +1,81 @@
 /*
- * Copyright 2015, Intel Corporation
- * Copyright (C) 2015 The Android Open Source Project
+ * 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
+ *      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.
- *
- * Written by William Roberts <william.c.roberts@intel.com>
- *
- * This is a parser library for parsing the packages.list file generated
- * by PackageManager service.
- *
- * This simple parser is sensitive to format changes in
- * frameworks/base/services/core/java/com/android/server/pm/Settings.java
- * A dependency note has been added to that file to correct
- * this parser.
  */
 
-#ifndef PACKAGELISTPARSER_H_
-#define PACKAGELISTPARSER_H_
+#pragma once
 
 #include <stdbool.h>
-#include <sys/cdefs.h>
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
-/** The file containing the list of installed packages on the system */
-#define PACKAGES_LIST_FILE  "/data/system/packages.list"
+typedef struct gid_list {
+  /** Number of gids. */
+  size_t cnt;
 
-typedef struct pkg_info pkg_info;
-typedef struct gid_list gid_list;
+  /** Array of gids. */
+  gid_t* gids;
+} gid_list;
 
-struct gid_list {
-    size_t cnt;
-    gid_t *gids;
-};
+typedef struct pkg_info {
+  /** Package name like "com.android.blah". */
+  char* name;
 
-struct pkg_info {
-    char *name;
-    uid_t uid;
-    bool debuggable;
-    char *data_dir;
-    char *seinfo;
-    gid_list gids;
-    void *private_data;
-    bool profileable_from_shell;
-    long version_code;
-};
+  /** Package uid like 10014. */
+  uid_t uid;
+
+  /** Package's AndroidManifest.xml debuggable flag. */
+  bool debuggable;
+
+  /** Package data directory like "/data/user/0/com.android.blah" */
+  char* data_dir;
+
+  /** Package SELinux info. */
+  char* seinfo;
+
+  /** Package's list of gids. */
+  gid_list gids;
+
+  /** Spare pointer for the caller to stash extra data off. */
+  void* private_data;
+
+  /** Package's AndroidManifest.xml profileable flag. */
+  bool profileable_from_shell;
+
+  /** Package's AndroidManifest.xml version code. */
+  long version_code;
+} pkg_info;
 
 /**
- * Callback function to be used by packagelist_parse() routine.
- * @param info
- *  The parsed package information
- * @param userdata
- *  The supplied userdata pointer to packagelist_parse()
- * @return
- *  true to keep processing, false to stop.
+ * Parses the system's default package list.
+ * Invokes `callback` once for each package.
+ * The callback owns the `pkg_info*` and should call packagelist_free().
+ * The callback should return `false` to exit early or `true` to continue.
  */
-typedef bool (*pfn_on_package)(pkg_info *info, void *userdata);
+bool packagelist_parse(bool (*callback)(pkg_info* info, void* user_data), void* user_data);
 
 /**
- * Parses the file specified by PACKAGES_LIST_FILE and invokes the callback on
- * each entry found. Once the callback is invoked, ownership of the pkg_info pointer
- * is passed to the callback routine, thus they are required to perform any cleanup
- * desired.
- * @param callback
- *  The callback function called on each parsed line of the packages list.
- * @param userdata
- *  An optional userdata supplied pointer to pass to the callback function.
- * @return
- *  true on success false on failure.
+ * Parses the given package list.
+ * Invokes `callback` once for each package.
+ * The callback owns the `pkg_info*` and should call packagelist_free().
+ * The callback should return `false` to exit early or `true` to continue.
  */
-extern bool packagelist_parse(pfn_on_package callback, void *userdata);
+bool packagelist_parse_file(const char* path, bool (*callback)(pkg_info* info, void* user_data),
+                            void* user_data);
 
-/**
- * Frees a pkg_info structure.
- * @param info
- *  The struct to free
- */
-extern void packagelist_free(pkg_info *info);
+/** Frees the given `pkg_info`. */
+void packagelist_free(pkg_info* info);
 
 __END_DECLS
-
-#endif /* PACKAGELISTPARSER_H_ */
diff --git a/libpackagelistparser/packagelistparser.c b/libpackagelistparser/packagelistparser.c
deleted file mode 100644
index edc533c..0000000
--- a/libpackagelistparser/packagelistparser.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright 2015, Intel Corporation
- * Copyright (C) 2015 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.
- *
- * Written by William Roberts <william.c.roberts@intel.com>
- *
- */
-
-#define LOG_TAG "packagelistparser"
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/limits.h>
-
-#include <log/log.h>
-#include <packagelistparser/packagelistparser.h>
-
-#define CLOGE(fmt, ...) \
-    do {\
-        IF_ALOGE() {\
-            ALOGE(fmt, ##__VA_ARGS__);\
-        }\
-    } while(0)
-
-static size_t get_gid_cnt(const char *gids)
-{
-    size_t cnt;
-
-    if (*gids == '\0') {
-        return 0;
-    }
-
-    if (!strcmp(gids, "none")) {
-        return 0;
-    }
-
-    for (cnt = 1; gids[cnt]; gids[cnt] == ',' ? cnt++ : *gids++)
-        ;
-
-    return cnt;
-}
-
-static bool parse_gids(char *gids, gid_t *gid_list, size_t *cnt)
-{
-    gid_t gid;
-    char* token;
-    char *endptr;
-    size_t cmp = 0;
-
-    while ((token = strsep(&gids, ",\r\n"))) {
-
-        if (cmp > *cnt) {
-            return false;
-        }
-
-        gid = strtoul(token, &endptr, 10);
-        if (*endptr != '\0') {
-            return false;
-        }
-
-        /*
-         * if unsigned long is greater than size of gid_t,
-         * prevent a truncation based roll-over
-         */
-        if (gid > GID_MAX) {
-            CLOGE("A gid in field \"gid list\" greater than GID_MAX");
-            return false;
-        }
-
-        gid_list[cmp++] = gid;
-    }
-    return true;
-}
-
-extern bool packagelist_parse(pfn_on_package callback, void *userdata)
-{
-
-    FILE *fp;
-    char *cur;
-    char *next;
-    char *endptr;
-    unsigned long tmp;
-    ssize_t bytesread;
-
-    bool rc = false;
-    char *buf = NULL;
-    size_t buflen = 0;
-    unsigned long lineno = 1;
-    const char *errmsg = NULL;
-    struct pkg_info *pkg_info = NULL;
-
-    fp = fopen(PACKAGES_LIST_FILE, "re");
-    if (!fp) {
-        CLOGE("Could not open: \"%s\", error: \"%s\"\n", PACKAGES_LIST_FILE,
-                strerror(errno));
-        return false;
-    }
-
-    while ((bytesread = getline(&buf, &buflen, fp)) > 0) {
-
-        pkg_info = calloc(1, sizeof(*pkg_info));
-        if (!pkg_info) {
-            goto err;
-        }
-
-        next = buf;
-
-        cur = strsep(&next, " \t\r\n");
-        if (!cur) {
-            errmsg = "Could not get next token for \"package name\"";
-            goto err;
-        }
-
-        pkg_info->name = strdup(cur);
-        if (!pkg_info->name) {
-            goto err;
-        }
-
-        cur = strsep(&next, " \t\r\n");
-        if (!cur) {
-            errmsg = "Could not get next token for field \"uid\"";
-            goto err;
-        }
-
-        tmp = strtoul(cur, &endptr, 10);
-        if (*endptr != '\0') {
-            errmsg = "Could not convert field \"uid\" to integer value";
-            goto err;
-        }
-
-        /*
-         * if unsigned long is greater than size of uid_t,
-         * prevent a truncation based roll-over
-         */
-        if (tmp > UID_MAX) {
-            errmsg = "Field \"uid\" greater than UID_MAX";
-            goto err;
-        }
-
-        pkg_info->uid = (uid_t) tmp;
-
-        cur = strsep(&next, " \t\r\n");
-        if (!cur) {
-            errmsg = "Could not get next token for field \"debuggable\"";
-            goto err;
-        }
-
-        tmp = strtoul(cur, &endptr, 10);
-        if (*endptr != '\0') {
-            errmsg = "Could not convert field \"debuggable\" to integer value";
-            goto err;
-        }
-
-        /* should be a valid boolean of 1 or 0 */
-        if (!(tmp == 0 || tmp == 1)) {
-            errmsg = "Field \"debuggable\" is not 0 or 1 boolean value";
-            goto err;
-        }
-
-        pkg_info->debuggable = (bool) tmp;
-
-        cur = strsep(&next, " \t\r\n");
-        if (!cur) {
-            errmsg = "Could not get next token for field \"data dir\"";
-            goto err;
-        }
-
-        pkg_info->data_dir = strdup(cur);
-        if (!pkg_info->data_dir) {
-            goto err;
-        }
-
-        cur = strsep(&next, " \t\r\n");
-        if (!cur) {
-            errmsg = "Could not get next token for field \"seinfo\"";
-            goto err;
-        }
-
-        pkg_info->seinfo = strdup(cur);
-        if (!pkg_info->seinfo) {
-            goto err;
-        }
-
-        cur = strsep(&next, " \t\r\n");
-        if (!cur) {
-            errmsg = "Could not get next token for field \"gid(s)\"";
-            goto err;
-        }
-
-        /*
-         * Parse the gid list, could be in the form of none, single gid or list:
-         * none
-         * gid
-         * gid, gid ...
-         */
-        pkg_info->gids.cnt = get_gid_cnt(cur);
-        if (pkg_info->gids.cnt > 0) {
-
-            pkg_info->gids.gids = calloc(pkg_info->gids.cnt, sizeof(gid_t));
-            if (!pkg_info->gids.gids) {
-                goto err;
-            }
-
-            rc = parse_gids(cur, pkg_info->gids.gids, &pkg_info->gids.cnt);
-            if (!rc) {
-                errmsg = "Could not parse field \"gid list\"";
-                goto err;
-            }
-        }
-
-        cur = strsep(&next, " \t\r\n");
-        if (cur) {
-            tmp = strtoul(cur, &endptr, 10);
-            if (*endptr != '\0') {
-                errmsg = "Could not convert field \"profileable_from_shell\" to integer value";
-                goto err;
-            }
-
-            /* should be a valid boolean of 1 or 0 */
-            if (!(tmp == 0 || tmp == 1)) {
-                errmsg = "Field \"profileable_from_shell\" is not 0 or 1 boolean value";
-                goto err;
-            }
-
-            pkg_info->profileable_from_shell = (bool)tmp;
-        }
-        cur = strsep(&next, " \t\r\n");
-        if (cur) {
-            tmp = strtoul(cur, &endptr, 10);
-            if (*endptr != '\0') {
-                errmsg = "Could not convert field \"versionCode\" to integer value";
-                goto err;
-            }
-            pkg_info->version_code = tmp;
-        }
-
-        rc = callback(pkg_info, userdata);
-        if (rc == false) {
-            /*
-             * We do not log this as this can be intentional from
-             * callback to abort processing. We go to out to not
-             * free the pkg_info
-             */
-            rc = true;
-            goto out;
-        }
-        lineno++;
-    }
-
-    rc = true;
-
-out:
-    free(buf);
-    fclose(fp);
-    return rc;
-
-err:
-    if (errmsg) {
-        CLOGE("Error Parsing \"%s\" on line: %lu for reason: %s",
-                PACKAGES_LIST_FILE, lineno, errmsg);
-    }
-    rc = false;
-    packagelist_free(pkg_info);
-    goto out;
-}
-
-void packagelist_free(pkg_info *info)
-{
-    if (info) {
-        free(info->name);
-        free(info->data_dir);
-        free(info->seinfo);
-        free(info->gids.gids);
-        free(info);
-    }
-}
diff --git a/libpackagelistparser/packagelistparser.cpp b/libpackagelistparser/packagelistparser.cpp
new file mode 100644
index 0000000..59c3a74
--- /dev/null
+++ b/libpackagelistparser/packagelistparser.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "packagelistparser"
+
+#include <packagelistparser/packagelistparser.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/limits.h>
+
+#include <memory>
+
+#include <log/log.h>
+
+static bool parse_gids(const char* path, size_t line_number, const char* gids, pkg_info* info) {
+  // Nothing to do?
+  if (!gids || !strcmp(gids, "none")) return true;
+
+  // How much space do we need?
+  info->gids.cnt = 1;
+  for (const char* p = gids; *p; ++p) {
+    if (*p == ',') ++info->gids.cnt;
+  }
+
+  // Allocate the space.
+  info->gids.gids = new gid_t[info->gids.cnt];
+  if (!info->gids.gids) return false;
+
+  // And parse the individual gids.
+  size_t i = 0;
+  while (true) {
+    char* end;
+    unsigned long gid = strtoul(gids, &end, 10);
+    if (gid > GID_MAX) {
+      ALOGE("%s:%zu: gid %lu > GID_MAX", path, line_number, gid);
+      return false;
+    }
+
+    if (i >= info->gids.cnt) return false;
+    info->gids.gids[i++] = gid;
+
+    if (*end == '\0') return true;
+    if (*end != ',') return false;
+    gids = end + 1;
+  }
+  return true;
+}
+
+static bool parse_line(const char* path, size_t line_number, const char* line, pkg_info* info) {
+  unsigned long uid;
+  int debuggable;
+  char* gid_list;
+  int profileable_from_shell = 0;
+
+  int fields =
+      sscanf(line, "%ms %lu %d %ms %ms %ms %d %ld", &info->name, &uid, &debuggable, &info->data_dir,
+             &info->seinfo, &gid_list, &profileable_from_shell, &info->version_code);
+
+  // Handle the more complicated gids field and free the temporary string.
+  bool gids_okay = parse_gids(path, line_number, gid_list, info);
+  free(gid_list);
+  if (!gids_okay) return false;
+
+  // Did we see enough fields to be getting on with?
+  // The final fields are optional (and not usually present).
+  if (fields < 6) {
+    ALOGE("%s:%zu: too few fields in line", path, line_number);
+    return false;
+  }
+
+  // Extra validation.
+  if (uid > UID_MAX) {
+    ALOGE("%s:%zu: uid %lu > UID_MAX", path, line_number, uid);
+    return false;
+  }
+  info->uid = uid;
+
+  // Integer to bool conversions.
+  info->debuggable = debuggable;
+  info->profileable_from_shell = profileable_from_shell;
+
+  return true;
+}
+
+bool packagelist_parse_file(const char* path, bool (*callback)(pkg_info*, void*), void* user_data) {
+  std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(path, "re"), &fclose);
+  if (!fp) {
+    ALOGE("couldn't open '%s': %s", path, strerror(errno));
+    return false;
+  }
+
+  size_t line_number = 0;
+  char* line = nullptr;
+  size_t allocated_length = 0;
+  while (getline(&line, &allocated_length, fp.get()) > 0) {
+    ++line_number;
+    std::unique_ptr<pkg_info, decltype(&packagelist_free)> info(
+        static_cast<pkg_info*>(calloc(1, sizeof(pkg_info))), &packagelist_free);
+    if (!info) {
+      ALOGE("%s:%zu: couldn't allocate pkg_info", path, line_number);
+      return false;
+    }
+
+    if (!parse_line(path, line_number, line, info.get())) return false;
+
+    if (!callback(info.release(), user_data)) break;
+  }
+  free(line);
+  return true;
+}
+
+bool packagelist_parse(bool (*callback)(pkg_info*, void*), void* user_data) {
+  return packagelist_parse_file("/data/system/packages.list", callback, user_data);
+}
+
+void packagelist_free(pkg_info* info) {
+  if (!info) return;
+
+  free(info->name);
+  free(info->data_dir);
+  free(info->seinfo);
+  delete[] info->gids.gids;
+  free(info);
+}
diff --git a/libpackagelistparser/packagelistparser_test.cpp b/libpackagelistparser/packagelistparser_test.cpp
new file mode 100644
index 0000000..76cb886
--- /dev/null
+++ b/libpackagelistparser/packagelistparser_test.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 <packagelistparser/packagelistparser.h>
+
+#include <memory>
+
+#include <android-base/file.h>
+
+#include <gtest/gtest.h>
+
+TEST(packagelistparser, smoke) {
+  TemporaryFile tf;
+  android::base::WriteStringToFile(
+      // No gids.
+      "com.test.a0 10014 0 /data/user/0/com.test.a0 platform:privapp:targetSdkVersion=19 none\n"
+      // One gid.
+      "com.test.a1 10007 1 /data/user/0/com.test.a1 platform:privapp:targetSdkVersion=21 1023\n"
+      // Multiple gids.
+      "com.test.a2 10011 0 /data/user/0/com.test.a2 media:privapp:targetSdkVersion=30 "
+      "2001,1065,1023,3003,3007,1024\n"
+      // The two new fields (profileable flag and version code).
+      "com.test.a3 10022 0 /data/user/0/com.test.a3 selabel:blah none 1 123\n",
+      tf.path);
+
+  std::vector<pkg_info*> packages;
+  packagelist_parse_file(
+      tf.path,
+      [](pkg_info* info, void* user_data) -> bool {
+        reinterpret_cast<std::vector<pkg_info*>*>(user_data)->push_back(info);
+        return true;
+      },
+      &packages);
+
+  ASSERT_EQ(4U, packages.size());
+
+  ASSERT_STREQ("com.test.a0", packages[0]->name);
+  ASSERT_EQ(10014, packages[0]->uid);
+  ASSERT_FALSE(packages[0]->debuggable);
+  ASSERT_STREQ("/data/user/0/com.test.a0", packages[0]->data_dir);
+  ASSERT_STREQ("platform:privapp:targetSdkVersion=19", packages[0]->seinfo);
+  ASSERT_EQ(0U, packages[0]->gids.cnt);
+  ASSERT_FALSE(packages[0]->profileable_from_shell);
+  ASSERT_EQ(0, packages[0]->version_code);
+
+  ASSERT_STREQ("com.test.a1", packages[1]->name);
+  ASSERT_EQ(10007, packages[1]->uid);
+  ASSERT_TRUE(packages[1]->debuggable);
+  ASSERT_STREQ("/data/user/0/com.test.a1", packages[1]->data_dir);
+  ASSERT_STREQ("platform:privapp:targetSdkVersion=21", packages[1]->seinfo);
+  ASSERT_EQ(1U, packages[1]->gids.cnt);
+  ASSERT_EQ(1023U, packages[1]->gids.gids[0]);
+  ASSERT_FALSE(packages[0]->profileable_from_shell);
+  ASSERT_EQ(0, packages[0]->version_code);
+
+  ASSERT_STREQ("com.test.a2", packages[2]->name);
+  ASSERT_EQ(10011, packages[2]->uid);
+  ASSERT_FALSE(packages[2]->debuggable);
+  ASSERT_STREQ("/data/user/0/com.test.a2", packages[2]->data_dir);
+  ASSERT_STREQ("media:privapp:targetSdkVersion=30", packages[2]->seinfo);
+  ASSERT_EQ(6U, packages[2]->gids.cnt);
+  ASSERT_EQ(2001U, packages[2]->gids.gids[0]);
+  ASSERT_EQ(1024U, packages[2]->gids.gids[5]);
+  ASSERT_FALSE(packages[0]->profileable_from_shell);
+  ASSERT_EQ(0, packages[0]->version_code);
+
+  ASSERT_STREQ("com.test.a3", packages[3]->name);
+  ASSERT_EQ(10022, packages[3]->uid);
+  ASSERT_FALSE(packages[3]->debuggable);
+  ASSERT_STREQ("/data/user/0/com.test.a3", packages[3]->data_dir);
+  ASSERT_STREQ("selabel:blah", packages[3]->seinfo);
+  ASSERT_EQ(0U, packages[3]->gids.cnt);
+  ASSERT_TRUE(packages[3]->profileable_from_shell);
+  ASSERT_EQ(123, packages[3]->version_code);
+
+  for (auto& package : packages) packagelist_free(package);
+}
+
+TEST(packagelistparser, early_exit) {
+  TemporaryFile tf;
+  android::base::WriteStringToFile(
+      "com.test.a0 1 0 / a none\n"
+      "com.test.a1 1 0 / a none\n"
+      "com.test.a2 1 0 / a none\n",
+      tf.path);
+
+  std::vector<pkg_info*> packages;
+  packagelist_parse_file(
+      tf.path,
+      [](pkg_info* info, void* user_data) -> bool {
+        std::vector<pkg_info*>* p = reinterpret_cast<std::vector<pkg_info*>*>(user_data);
+        p->push_back(info);
+        return p->size() < 2;
+      },
+      &packages);
+
+  ASSERT_EQ(2U, packages.size());
+
+  ASSERT_STREQ("com.test.a0", packages[0]->name);
+  ASSERT_STREQ("com.test.a1", packages[1]->name);
+
+  for (auto& package : packages) packagelist_free(package);
+}
+
+TEST(packagelistparser, system_package_list) {
+  // Check that we can actually read the packages.list installed on the device.
+  std::vector<pkg_info*> packages;
+  packagelist_parse(
+      [](pkg_info* info, void* user_data) -> bool {
+        reinterpret_cast<std::vector<pkg_info*>*>(user_data)->push_back(info);
+        return true;
+      },
+      &packages);
+  // Not much we can say for sure about what we expect, other than that there
+  // are likely to be lots of packages...
+  ASSERT_GT(packages.size(), 10U);
+}
+
+TEST(packagelistparser, packagelist_free_nullptr) {
+  packagelist_free(nullptr);
+}
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index 0207a75..618a5c5 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -3,6 +3,7 @@
     vendor_available: true,
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
     target: {
         linux_bionic: {
@@ -23,6 +24,7 @@
     ],
     name: "libprocessgroup",
     host_supported: true,
+    native_bridge_supported: true,
     recovery_available: true,
     vendor_available: true,
     vndk: {
diff --git a/libprocessgroup/OWNERS b/libprocessgroup/OWNERS
index bfa730a..27b9a03 100644
--- a/libprocessgroup/OWNERS
+++ b/libprocessgroup/OWNERS
@@ -1,2 +1,3 @@
 ccross@google.com
+surenb@google.com
 tomcherry@google.com
diff --git a/libprocessgroup/cgrouprc/Android.bp b/libprocessgroup/cgrouprc/Android.bp
index 9d5afeb..0af75bb 100644
--- a/libprocessgroup/cgrouprc/Android.bp
+++ b/libprocessgroup/cgrouprc/Android.bp
@@ -21,6 +21,7 @@
     // modules should use libprocessgroup which links to the LL-NDK library
     // defined below. The static library is built for tests.
     vendor_available: false,
+    native_bridge_supported: true,
     srcs: [
         "cgroup_controller.cpp",
         "cgroup_file.cpp",
@@ -55,6 +56,7 @@
 llndk_library {
     name: "libcgrouprc",
     symbol_file: "libcgrouprc.llndk.txt",
+    native_bridge_supported: true,
     export_include_dirs: [
         "include",
     ],
diff --git a/libprocessgroup/cgrouprc_format/Android.bp b/libprocessgroup/cgrouprc_format/Android.bp
index dfbeed7..559a869 100644
--- a/libprocessgroup/cgrouprc_format/Android.bp
+++ b/libprocessgroup/cgrouprc_format/Android.bp
@@ -16,6 +16,7 @@
     name: "libcgrouprc_format",
     host_supported: true,
     recovery_available: true,
+    native_bridge_supported: true,
     srcs: [
         "cgroup_controller.cpp",
     ],
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 7e6bf45..0b38b6b 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -39,14 +39,22 @@
 
 bool UsePerAppMemcg();
 
+// Drop the fd cache of cgroup path. It is used for when resource caching is enabled and a process
+// loses the access to the path, the access checking (See SetCgroupAction::EnableResourceCaching)
+// should be active again. E.g. Zygote specialization for child process.
+void DropTaskProfilesResourceCaching();
+
 // Return 0 and removes the cgroup if there are no longer any processes in it.
 // Returns -1 in the case of an error occurring or if there are processes still running
 // even after retrying for up to 200ms.
-int killProcessGroup(uid_t uid, int initialPid, int signal);
+// If max_processes is not nullptr, it returns the maximum number of processes seen in the cgroup
+// during the killing process.  Note that this can be 0 if all processes from the process group have
+// already been terminated.
+int killProcessGroup(uid_t uid, int initialPid, int signal, int* max_processes = nullptr);
 
 // Returns the same as killProcessGroup(), however it does not retry, which means
 // that it only returns 0 in the case that the cgroup exists and it contains no processes.
-int killProcessGroupOnce(uid_t uid, int initialPid, int signal);
+int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes = nullptr);
 
 int createProcessGroup(uid_t uid, int initialPid, bool memControl = false);
 
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
index 3c498da..945d90c 100644
--- a/libprocessgroup/include/processgroup/sched_policy.h
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -70,11 +70,22 @@
 extern int get_sched_policy(int tid, SchedPolicy* policy);
 
 /* Return a displayable string corresponding to policy.
- * Return value: non-NULL NUL-terminated name of unspecified length;
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
  * the caller is responsible for displaying the useful part of the string.
  */
 extern const char* get_sched_policy_name(SchedPolicy policy);
 
+/* Return the aggregated task profile name corresponding to cpuset policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_cpuset_policy_profile_name(SchedPolicy policy);
+
+/* Return the aggregated task profile name corresponding to sched policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_sched_policy_profile_name(SchedPolicy policy);
 #ifdef __cplusplus
 }
 #endif
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index d3ac26b..6272664 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -111,45 +111,17 @@
     return memcg_supported;
 }
 
+void DropTaskProfilesResourceCaching() {
+    TaskProfiles::GetInstance().DropResourceCaching();
+}
+
 bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
                         bool use_fd_cache) {
-    const TaskProfiles& tp = TaskProfiles::GetInstance();
-
-    for (const auto& name : profiles) {
-        TaskProfile* profile = tp.GetProfile(name);
-        if (profile != nullptr) {
-            if (use_fd_cache) {
-                profile->EnableResourceCaching();
-            }
-            if (!profile->ExecuteForProcess(uid, pid)) {
-                PLOG(WARNING) << "Failed to apply " << name << " process profile";
-            }
-        } else {
-            PLOG(WARNING) << "Failed to find " << name << "process profile";
-        }
-    }
-
-    return true;
+    return TaskProfiles::GetInstance().SetProcessProfiles(uid, pid, profiles, use_fd_cache);
 }
 
 bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache) {
-    const TaskProfiles& tp = TaskProfiles::GetInstance();
-
-    for (const auto& name : profiles) {
-        TaskProfile* profile = tp.GetProfile(name);
-        if (profile != nullptr) {
-            if (use_fd_cache) {
-                profile->EnableResourceCaching();
-            }
-            if (!profile->ExecuteForTask(tid)) {
-                PLOG(WARNING) << "Failed to apply " << name << " task profile";
-            }
-        } else {
-            PLOG(WARNING) << "Failed to find " << name << "task profile";
-        }
-    }
-
-    return true;
+    return TaskProfiles::GetInstance().SetTaskProfiles(tid, profiles, use_fd_cache);
 }
 
 static std::string ConvertUidToPath(const char* cgroup, uid_t uid) {
@@ -329,7 +301,8 @@
     return feof(fd.get()) ? processes : -1;
 }
 
-static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) {
+static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries,
+                            int* max_processes) {
     std::string cpuacct_path;
     std::string memory_path;
 
@@ -344,9 +317,16 @@
 
     std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
 
+    if (max_processes != nullptr) {
+        *max_processes = 0;
+    }
+
     int retry = retries;
     int processes;
     while ((processes = DoKillProcessGroupOnce(cgroup, uid, initialPid, signal)) > 0) {
+        if (max_processes != nullptr && processes > *max_processes) {
+            *max_processes = processes;
+        }
         LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid;
         if (retry > 0) {
             std::this_thread::sleep_for(5ms);
@@ -387,12 +367,12 @@
     }
 }
 
-int killProcessGroup(uid_t uid, int initialPid, int signal) {
-    return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/);
+int killProcessGroup(uid_t uid, int initialPid, int signal, int* max_processes) {
+    return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/, max_processes);
 }
 
-int killProcessGroupOnce(uid_t uid, int initialPid, int signal) {
-    return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/);
+int killProcessGroupOnce(uid_t uid, int initialPid, int signal, int* max_processes) {
+    return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/, max_processes);
 }
 
 int createProcessGroup(uid_t uid, int initialPid, bool memControl) {
diff --git a/libprocessgroup/profiles/cgroups.json b/libprocessgroup/profiles/cgroups.json
index 5871a63..0341902 100644
--- a/libprocessgroup/profiles/cgroups.json
+++ b/libprocessgroup/profiles/cgroups.json
@@ -39,6 +39,13 @@
       "Mode": "0755",
       "UID": "system",
       "GID": "system"
+    },
+    {
+      "Controller": "freezer",
+      "Path": "/dev/freezer",
+      "Mode": "0755",
+      "UID": "system",
+      "GID": "system"
     }
   ],
   "Cgroups2": {
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 74a39cd..3f3dbd7 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -15,7 +15,6 @@
       "Controller": "cpuset",
       "File": "top-app/cpus"
     },
-
     {
       "Name": "MemLimit",
       "Controller": "memory",
@@ -68,6 +67,32 @@
       ]
     },
     {
+      "Name": "Frozen",
+      "Actions": [
+        {
+          "Name": "JoinCgroup",
+          "Params":
+          {
+            "Controller": "freezer",
+            "Path": "frozen"
+          }
+        }
+      ]
+    },
+    {
+      "Name": "Unfrozen",
+      "Actions": [
+        {
+          "Name": "JoinCgroup",
+          "Params":
+          {
+            "Controller": "freezer",
+            "Path": ""
+          }
+        }
+      ]
+    },
+    {
       "Name": "NormalPerformance",
       "Actions": [
         {
@@ -494,5 +519,52 @@
         }
       ]
     }
+  ],
+
+  "AggregateProfiles": [
+    {
+      "Name": "SCHED_SP_DEFAULT",
+      "Profiles": [ "TimerSlackNormal" ]
+    },
+    {
+      "Name": "SCHED_SP_BACKGROUND",
+      "Profiles": [ "HighEnergySaving", "LowIoPriority", "TimerSlackHigh" ]
+    },
+    {
+      "Name": "SCHED_SP_FOREGROUND",
+      "Profiles": [ "HighPerformance", "HighIoPriority", "TimerSlackNormal" ]
+    },
+    {
+      "Name": "SCHED_SP_TOP_APP",
+      "Profiles": [ "MaxPerformance", "MaxIoPriority", "TimerSlackNormal" ]
+    },
+    {
+      "Name": "SCHED_SP_RT_APP",
+      "Profiles": [ "RealtimePerformance", "MaxIoPriority", "TimerSlackNormal" ]
+    },
+    {
+      "Name": "CPUSET_SP_DEFAULT",
+      "Profiles": [ "TimerSlackNormal" ]
+    },
+    {
+      "Name": "CPUSET_SP_BACKGROUND",
+      "Profiles": [ "HighEnergySaving", "ProcessCapacityLow", "LowIoPriority", "TimerSlackHigh" ]
+    },
+    {
+      "Name": "CPUSET_SP_FOREGROUND",
+      "Profiles": [ "HighPerformance", "ProcessCapacityHigh", "HighIoPriority", "TimerSlackNormal" ]
+    },
+    {
+      "Name": "CPUSET_SP_TOP_APP",
+      "Profiles": [ "MaxPerformance", "ProcessCapacityMax", "MaxIoPriority", "TimerSlackNormal" ]
+    },
+    {
+      "Name": "CPUSET_SP_SYSTEM",
+      "Profiles": [ "ServiceCapacityLow", "TimerSlackNormal" ]
+    },
+    {
+      "Name": "CPUSET_SP_RESTRICTED",
+      "Profiles": [ "ServiceCapacityRestricted", "TimerSlackNormal" ]
+    }
   ]
 }
diff --git a/libprocessgroup/profiles/task_profiles.proto b/libprocessgroup/profiles/task_profiles.proto
index 578f0d3..1de4395 100644
--- a/libprocessgroup/profiles/task_profiles.proto
+++ b/libprocessgroup/profiles/task_profiles.proto
@@ -18,10 +18,11 @@
 
 package android.profiles;
 
-// Next: 3
+// Next: 4
 message TaskProfiles {
     repeated Attribute attributes = 1 [json_name = "Attributes"];
     repeated Profile profiles = 2 [json_name = "Profiles"];
+    repeated AggregateProfiles aggregateprofiles = 3 [json_name = "AggregateProfiles"];
 }
 
 // Next: 4
@@ -42,3 +43,9 @@
     string name = 1 [json_name = "Name"];
     map<string, string> params = 2 [json_name = "Params"];
 }
+
+// Next: 3
+message AggregateProfiles {
+    string name = 1 [json_name = "Name"];
+    repeated string profiles = 2 [json_name = "Profiles"];
+}
diff --git a/libprocessgroup/profiles/test.cpp b/libprocessgroup/profiles/test.cpp
index bc9aade..b37e3e6 100644
--- a/libprocessgroup/profiles/test.cpp
+++ b/libprocessgroup/profiles/test.cpp
@@ -33,14 +33,14 @@
 }
 
 // Test suite instantiations
-INSTANTIATE_TEST_SUITE_P(, JsonSchemaTest,
+INSTANTIATE_TEST_SUITE_P(Cgroups, JsonSchemaTest,
                          ::testing::Values(MakeTestParam<Cgroups>("/cgroups.json"),
                                            MakeTestParam<Cgroups>("/cgroups.recovery.json"),
                                            MakeTestParam<TaskProfiles>("/task_profiles.json")));
-INSTANTIATE_TEST_SUITE_P(, CgroupsTest,
+INSTANTIATE_TEST_SUITE_P(Cgroups, CgroupsTest,
                          ::testing::Values(MakeTestParam<Cgroups>("/cgroups.json"),
                                            MakeTestParam<Cgroups>("/cgroups.recovery.json")));
-INSTANTIATE_TEST_SUITE_P(, TaskProfilesTest,
+INSTANTIATE_TEST_SUITE_P(TaskProfiles, TaskProfilesTest,
                          ::testing::Values(MakeTestParam<TaskProfiles>("/task_profiles.json")));
 
 }  // namespace profiles
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 15f8139..16339d3 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -46,34 +46,17 @@
 
     switch (policy) {
         case SP_BACKGROUND:
-            return SetTaskProfiles(tid,
-                                   {"HighEnergySaving", "ProcessCapacityLow", "LowIoPriority",
-                                    "TimerSlackHigh"},
-                                   true)
-                           ? 0
-                           : -1;
+            return SetTaskProfiles(tid, {"CPUSET_SP_BACKGROUND"}, true) ? 0 : -1;
         case SP_FOREGROUND:
         case SP_AUDIO_APP:
         case SP_AUDIO_SYS:
-            return SetTaskProfiles(tid,
-                                   {"HighPerformance", "ProcessCapacityHigh", "HighIoPriority",
-                                    "TimerSlackNormal"},
-                                   true)
-                           ? 0
-                           : -1;
+            return SetTaskProfiles(tid, {"CPUSET_SP_FOREGROUND"}, true) ? 0 : -1;
         case SP_TOP_APP:
-            return SetTaskProfiles(tid,
-                                   {"MaxPerformance", "ProcessCapacityMax", "MaxIoPriority",
-                                    "TimerSlackNormal"},
-                                   true)
-                           ? 0
-                           : -1;
+            return SetTaskProfiles(tid, {"CPUSET_SP_TOP_APP"}, true) ? 0 : -1;
         case SP_SYSTEM:
-            return SetTaskProfiles(tid, {"ServiceCapacityLow", "TimerSlackNormal"}, true) ? 0 : -1;
+            return SetTaskProfiles(tid, {"CPUSET_SP_SYSTEM"}, true) ? 0 : -1;
         case SP_RESTRICTED:
-            return SetTaskProfiles(tid, {"ServiceCapacityRestricted", "TimerSlackNormal"}, true)
-                           ? 0
-                           : -1;
+            return SetTaskProfiles(tid, {"CPUSET_SP_RESTRICTED"}, true) ? 0 : -1;
         default:
             break;
     }
@@ -134,17 +117,17 @@
 
     switch (policy) {
         case SP_BACKGROUND:
-            return SetTaskProfiles(tid, {"HighEnergySaving", "TimerSlackHigh"}, true) ? 0 : -1;
+            return SetTaskProfiles(tid, {"SCHED_SP_BACKGROUND"}, true) ? 0 : -1;
         case SP_FOREGROUND:
         case SP_AUDIO_APP:
         case SP_AUDIO_SYS:
-            return SetTaskProfiles(tid, {"HighPerformance", "TimerSlackNormal"}, true) ? 0 : -1;
+            return SetTaskProfiles(tid, {"SCHED_SP_FOREGROUND"}, true) ? 0 : -1;
         case SP_TOP_APP:
-            return SetTaskProfiles(tid, {"MaxPerformance", "TimerSlackNormal"}, true) ? 0 : -1;
+            return SetTaskProfiles(tid, {"SCHED_SP_TOP_APP"}, true) ? 0 : -1;
         case SP_RT_APP:
-            return SetTaskProfiles(tid, {"RealtimePerformance", "TimerSlackNormal"}, true) ? 0 : -1;
+            return SetTaskProfiles(tid, {"SCHED_SP_RT_APP"}, true) ? 0 : -1;
         default:
-            return SetTaskProfiles(tid, {"TimerSlackNormal"}, true) ? 0 : -1;
+            return SetTaskProfiles(tid, {"SCHED_SP_DEFAULT"}, true) ? 0 : -1;
     }
 
     return 0;
@@ -229,7 +212,45 @@
     };
     static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
     if (policy < SP_BACKGROUND || policy >= SP_CNT) {
-        return "error";
+        return nullptr;
     }
     return kSchedPolicyNames[policy];
 }
+
+const char* get_cpuset_policy_profile_name(SchedPolicy policy) {
+    /*
+     *  cpuset profile array for:
+     *  SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+     *  SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+     *  index is policy + 1
+     *  this need keep in sync with SchedPolicy enum
+     */
+    static constexpr const char* kCpusetProfiles[SP_CNT + 1] = {
+            "CPUSET_SP_DEFAULT", "CPUSET_SP_BACKGROUND", "CPUSET_SP_FOREGROUND",
+            "CPUSET_SP_SYSTEM",  "CPUSET_SP_FOREGROUND", "CPUSET_SP_FOREGROUND",
+            "CPUSET_SP_TOP_APP", "CPUSET_SP_DEFAULT",    "CPUSET_SP_RESTRICTED"};
+    if (policy < SP_DEFAULT || policy >= SP_CNT) {
+        return nullptr;
+    }
+    return kCpusetProfiles[policy + 1];
+}
+
+const char* get_sched_policy_profile_name(SchedPolicy policy) {
+    /*
+     *  sched profile array for:
+     *  SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+     *  SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+     *  SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+     *  index is policy + 1
+     *  this need keep in sync with SchedPolicy enum
+     */
+    static constexpr const char* kSchedProfiles[SP_CNT + 1] = {
+            "SCHED_SP_DEFAULT", "SCHED_SP_BACKGROUND", "SCHED_SP_FOREGROUND",
+            "SCHED_SP_DEFAULT", "SCHED_SP_FOREGROUND", "SCHED_SP_FOREGROUND",
+            "SCHED_SP_TOP_APP", "SCHED_SP_RT_APP",     "SCHED_SP_DEFAULT"};
+    if (policy < SP_DEFAULT || policy >= SP_CNT) {
+        return nullptr;
+    }
+    return kSchedProfiles[policy + 1];
+}
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index edc316a..9447f86 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -173,6 +173,15 @@
     fd_ = std::move(fd);
 }
 
+void SetCgroupAction::DropResourceCaching() {
+    std::lock_guard<std::mutex> lock(fd_mutex_);
+    if (fd_ == FDS_NOT_CACHED) {
+        return;
+    }
+
+    fd_.reset(FDS_NOT_CACHED);
+}
+
 bool SetCgroupAction::AddTidToCgroup(int tid, int fd) {
     if (tid <= 0) {
         return true;
@@ -259,6 +268,26 @@
     return true;
 }
 
+bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const {
+    for (const auto& profile : profiles_) {
+        profile->EnableResourceCaching();
+        if (!profile->ExecuteForProcess(uid, pid)) {
+            PLOG(WARNING) << "ExecuteForProcess failed for aggregate profile";
+        }
+    }
+    return true;
+}
+
+bool ApplyProfileAction::ExecuteForTask(int tid) const {
+    for (const auto& profile : profiles_) {
+        profile->EnableResourceCaching();
+        if (!profile->ExecuteForTask(tid)) {
+            PLOG(WARNING) << "ExecuteForTask failed for aggregate profile";
+        }
+    }
+    return true;
+}
+
 bool TaskProfile::ExecuteForProcess(uid_t uid, pid_t pid) const {
     for (const auto& element : elements_) {
         if (!element->ExecuteForProcess(uid, pid)) {
@@ -292,6 +321,24 @@
     res_cached_ = true;
 }
 
+void TaskProfile::DropResourceCaching() {
+    if (!res_cached_) {
+        return;
+    }
+
+    for (auto& element : elements_) {
+        element->DropResourceCaching();
+    }
+
+    res_cached_ = false;
+}
+
+void TaskProfiles::DropResourceCaching() const {
+    for (auto& iter : profiles_) {
+        iter.second->DropResourceCaching();
+    }
+}
+
 TaskProfiles& TaskProfiles::GetInstance() {
     // Deliberately leak this object to avoid a race between destruction on
     // process exit and concurrent access from another thread.
@@ -346,15 +393,13 @@
         }
     }
 
-    std::map<std::string, std::string> params;
-
     const Json::Value& profiles_val = root["Profiles"];
     for (Json::Value::ArrayIndex i = 0; i < profiles_val.size(); ++i) {
         const Json::Value& profile_val = profiles_val[i];
 
         std::string profile_name = profile_val["Name"].asString();
         const Json::Value& actions = profile_val["Actions"];
-        auto profile = std::make_unique<TaskProfile>();
+        auto profile = std::make_shared<TaskProfile>();
 
         for (Json::Value::ArrayIndex act_idx = 0; act_idx < actions.size(); ++act_idx) {
             const Json::Value& action_val = actions[act_idx];
@@ -413,7 +458,38 @@
                 LOG(WARNING) << "Unknown profile action: " << action_name;
             }
         }
-        profiles_[profile_name] = std::move(profile);
+        profiles_[profile_name] = profile;
+    }
+
+    const Json::Value& aggregateprofiles_val = root["AggregateProfiles"];
+    for (Json::Value::ArrayIndex i = 0; i < aggregateprofiles_val.size(); ++i) {
+        const Json::Value& aggregateprofile_val = aggregateprofiles_val[i];
+
+        std::string aggregateprofile_name = aggregateprofile_val["Name"].asString();
+        const Json::Value& aggregateprofiles = aggregateprofile_val["Profiles"];
+        std::vector<std::shared_ptr<TaskProfile>> profiles;
+        bool ret = true;
+
+        for (Json::Value::ArrayIndex pf_idx = 0; pf_idx < aggregateprofiles.size(); ++pf_idx) {
+            std::string profile_name = aggregateprofiles[pf_idx].asString();
+
+            if (profile_name == aggregateprofile_name) {
+                LOG(WARNING) << "AggregateProfiles: recursive profile name: " << profile_name;
+                ret = false;
+                break;
+            } else if (profiles_.find(profile_name) == profiles_.end()) {
+                LOG(WARNING) << "AggregateProfiles: undefined profile name: " << profile_name;
+                ret = false;
+                break;
+            } else {
+                profiles.push_back(profiles_[profile_name]);
+            }
+        }
+        if (ret) {
+            auto profile = std::make_shared<TaskProfile>();
+            profile->Add(std::make_unique<ApplyProfileAction>(profiles));
+            profiles_[aggregateprofile_name] = profile;
+        }
     }
 
     return true;
@@ -436,3 +512,39 @@
     }
     return nullptr;
 }
+
+bool TaskProfiles::SetProcessProfiles(uid_t uid, pid_t pid,
+                                      const std::vector<std::string>& profiles, bool use_fd_cache) {
+    for (const auto& name : profiles) {
+        TaskProfile* profile = GetProfile(name);
+        if (profile != nullptr) {
+            if (use_fd_cache) {
+                profile->EnableResourceCaching();
+            }
+            if (!profile->ExecuteForProcess(uid, pid)) {
+                PLOG(WARNING) << "Failed to apply " << name << " process profile";
+            }
+        } else {
+            PLOG(WARNING) << "Failed to find " << name << "process profile";
+        }
+    }
+    return true;
+}
+
+bool TaskProfiles::SetTaskProfiles(int tid, const std::vector<std::string>& profiles,
+                                   bool use_fd_cache) {
+    for (const auto& name : profiles) {
+        TaskProfile* profile = GetProfile(name);
+        if (profile != nullptr) {
+            if (use_fd_cache) {
+                profile->EnableResourceCaching();
+            }
+            if (!profile->ExecuteForTask(tid)) {
+                PLOG(WARNING) << "Failed to apply " << name << " task profile";
+            }
+        } else {
+            PLOG(WARNING) << "Failed to find " << name << "task profile";
+        }
+    }
+    return true;
+}
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 77bac2d..9f2308c 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -51,6 +51,7 @@
     virtual bool ExecuteForTask(int) const { return false; };
 
     virtual void EnableResourceCaching() {}
+    virtual void DropResourceCaching() {}
 };
 
 // Profile actions
@@ -114,6 +115,7 @@
     virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
     virtual bool ExecuteForTask(int tid) const;
     virtual void EnableResourceCaching();
+    virtual void DropResourceCaching();
 
     const CgroupController* controller() const { return &controller_; }
     std::string path() const { return path_; }
@@ -145,12 +147,26 @@
     bool ExecuteForProcess(uid_t uid, pid_t pid) const;
     bool ExecuteForTask(int tid) const;
     void EnableResourceCaching();
+    void DropResourceCaching();
 
   private:
     bool res_cached_;
     std::vector<std::unique_ptr<ProfileAction>> elements_;
 };
 
+// Set aggregate profile element
+class ApplyProfileAction : public ProfileAction {
+  public:
+    ApplyProfileAction(const std::vector<std::shared_ptr<TaskProfile>>& profiles)
+        : profiles_(profiles) {}
+
+    virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const;
+    virtual bool ExecuteForTask(int tid) const;
+
+  private:
+    std::vector<std::shared_ptr<TaskProfile>> profiles_;
+};
+
 class TaskProfiles {
   public:
     // Should be used by all users
@@ -158,9 +174,13 @@
 
     TaskProfile* GetProfile(const std::string& name) const;
     const ProfileAttribute* GetAttribute(const std::string& name) const;
+    void DropResourceCaching() const;
+    bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles,
+                            bool use_fd_cache);
+    bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache);
 
   private:
-    std::map<std::string, std::unique_ptr<TaskProfile>> profiles_;
+    std::map<std::string, std::shared_ptr<TaskProfile>> profiles_;
     std::map<std::string, std::unique_ptr<ProfileAttribute>> attributes_;
 
     TaskProfiles();
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 15f03d0..0c9a2b8 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -34,6 +34,7 @@
     host_supported: true,
     srcs: [
         "process.cpp",
+        "process_map.cpp",
     ],
 
     local_include_dirs: ["include"],
@@ -58,6 +59,7 @@
     name: "libprocinfo_test",
     defaults: ["libprocinfo_defaults"],
     host_supported: true,
+    isolated: true,
     srcs: [
         "process_test.cpp",
         "process_map_test.cpp",
diff --git a/libprocinfo/include/procinfo/process_map.h b/libprocinfo/include/procinfo/process_map.h
index b6ec3cb..569a022 100644
--- a/libprocinfo/include/procinfo/process_map.h
+++ b/libprocinfo/include/procinfo/process_map.h
@@ -176,5 +176,9 @@
                const char* name) { maps->emplace_back(start, end, flags, pgoff, inode, name); });
 }
 
+bool ReadMapFileAsyncSafe(const char* map_file, void* buffer, size_t buffer_size,
+                          const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
+                                                   const char*)>& callback);
+
 } /* namespace procinfo */
 } /* namespace android */
diff --git a/libprocinfo/process_map.cpp b/libprocinfo/process_map.cpp
new file mode 100644
index 0000000..5e240b9
--- /dev/null
+++ b/libprocinfo/process_map.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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 <procinfo/process_map.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <procinfo/process.h>
+
+namespace android {
+namespace procinfo {
+
+bool ReadMapFileAsyncSafe(const char* map_file, void* buffer, size_t buffer_size,
+                          const std::function<void(uint64_t, uint64_t, uint16_t, uint64_t, ino_t,
+                                                   const char*)>& callback) {
+  if (buffer == nullptr || buffer_size == 0) {
+    return false;
+  }
+
+  int fd = open(map_file, O_RDONLY | O_CLOEXEC);
+  if (fd == -1) {
+    return false;
+  }
+
+  char* char_buffer = reinterpret_cast<char*>(buffer);
+  size_t start = 0;
+  size_t read_bytes = 0;
+  char* line = nullptr;
+  bool read_complete = false;
+  while (true) {
+    ssize_t bytes =
+        TEMP_FAILURE_RETRY(read(fd, char_buffer + read_bytes, buffer_size - read_bytes - 1));
+    if (bytes <= 0) {
+      if (read_bytes == 0) {
+        close(fd);
+        return bytes == 0;
+      }
+      // Treat the last piece of data as the last line.
+      char_buffer[start + read_bytes] = '\n';
+      bytes = 1;
+      read_complete = true;
+    }
+    read_bytes += bytes;
+
+    while (read_bytes > 0) {
+      char* newline = reinterpret_cast<char*>(memchr(&char_buffer[start], '\n', read_bytes));
+      if (newline == nullptr) {
+        break;
+      }
+      *newline = '\0';
+      line = &char_buffer[start];
+      start = newline - char_buffer + 1;
+      read_bytes -= newline - line + 1;
+
+      // Ignore the return code, errors are okay.
+      ReadMapFileContent(line, callback);
+    }
+
+    if (read_complete) {
+      close(fd);
+      return true;
+    }
+
+    if (start == 0 && read_bytes == buffer_size - 1) {
+      // The buffer provided is too small to contain this line, give up
+      // and indicate failure.
+      close(fd);
+      return false;
+    }
+
+    // Copy any leftover data to the front  of the buffer.
+    if (start > 0) {
+      if (read_bytes > 0) {
+        memmove(char_buffer, &char_buffer[start], read_bytes);
+      }
+      start = 0;
+    }
+  }
+}
+
+} /* namespace procinfo */
+} /* namespace android */
diff --git a/libprocinfo/process_map_test.cpp b/libprocinfo/process_map_test.cpp
index 562d864..b1bdc08 100644
--- a/libprocinfo/process_map_test.cpp
+++ b/libprocinfo/process_map_test.cpp
@@ -16,9 +16,14 @@
 
 #include <procinfo/process_map.h>
 
+#include <inttypes.h>
+#include <sys/mman.h>
+
 #include <string>
+#include <vector>
 
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
 
 #include <gtest/gtest.h>
 
@@ -63,3 +68,215 @@
   ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps));
   ASSERT_GT(maps.size(), 0u);
 }
+
+extern "C" void malloc_disable();
+extern "C" void malloc_enable();
+
+struct TestMapInfo {
+  TestMapInfo() = default;
+  TestMapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
+              const char* new_name)
+      : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode) {
+    strcpy(name, new_name);
+  }
+  uint64_t start = 0;
+  uint64_t end = 0;
+  uint16_t flags = 0;
+  uint64_t pgoff = 0;
+  ino_t inode = 0;
+  char name[100] = {};
+};
+
+void VerifyReadMapFileAsyncSafe(const char* maps_data,
+                                const std::vector<TestMapInfo>& expected_info) {
+  TemporaryFile tf;
+  ASSERT_TRUE(android::base::WriteStringToFd(maps_data, tf.fd));
+
+  std::vector<TestMapInfo> saved_info(expected_info.size());
+  size_t num_maps = 0;
+
+  auto callback = [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
+                      const char* name) {
+    if (num_maps != saved_info.size()) {
+      TestMapInfo& saved = saved_info[num_maps];
+      saved.start = start;
+      saved.end = end;
+      saved.flags = flags;
+      saved.pgoff = pgoff;
+      saved.inode = inode;
+      strcpy(saved.name, name);
+    }
+    num_maps++;
+  };
+
+  std::vector<char> buffer(64 * 1024);
+
+#if defined(__BIONIC__)
+  // Any allocations will block after this call.
+  malloc_disable();
+#endif
+
+  bool parsed =
+      android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer.data(), buffer.size(), callback);
+
+#if defined(__BIONIC__)
+  malloc_enable();
+#endif
+
+  ASSERT_TRUE(parsed) << "Parsing of data failed:\n" << maps_data;
+  ASSERT_EQ(expected_info.size(), num_maps);
+  for (size_t i = 0; i < expected_info.size(); i++) {
+    const TestMapInfo& expected = expected_info[i];
+    const TestMapInfo& saved = saved_info[i];
+    EXPECT_EQ(expected.start, saved.start);
+    EXPECT_EQ(expected.end, saved.end);
+    EXPECT_EQ(expected.flags, saved.flags);
+    EXPECT_EQ(expected.pgoff, saved.pgoff);
+    EXPECT_EQ(expected.inode, saved.inode);
+    EXPECT_STREQ(expected.name, saved.name);
+  }
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_invalid) {
+  std::vector<TestMapInfo> expected_info;
+
+  VerifyReadMapFileAsyncSafe("12c00000-2ac00000", expected_info);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_single) {
+  std::vector<TestMapInfo> expected_info;
+  expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643,
+                             "/lib/fake.so");
+
+  VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so",
+                             expected_info);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_single_with_newline) {
+  std::vector<TestMapInfo> expected_info;
+  expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643,
+                             "/lib/fake.so");
+
+  VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so\n",
+                             expected_info);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_single_no_library) {
+  std::vector<TestMapInfo> expected_info;
+  expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 0xb00, 101, "");
+
+  VerifyReadMapFileAsyncSafe("a0000-c0000 rwxp 00000b00 00:05 101", expected_info);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_multiple) {
+  std::vector<TestMapInfo> expected_info;
+  expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 1, 100, "");
+  expected_info.emplace_back(0xd0000, 0xe0000, PROT_READ, 2, 101, "/lib/libsomething1.so");
+  expected_info.emplace_back(0xf0000, 0x100000, PROT_WRITE, 3, 102, "/lib/libsomething2.so");
+  expected_info.emplace_back(0x110000, 0x120000, PROT_EXEC, 4, 103, "[anon:something or another]");
+
+  std::string map_data =
+      "0a0000-0c0000 rwxp 00000001 00:05 100\n"
+      "0d0000-0e0000 r--p 00000002 00:05 101  /lib/libsomething1.so\n"
+      "0f0000-100000 -w-p 00000003 00:05 102  /lib/libsomething2.so\n"
+      "110000-120000 --xp 00000004 00:05 103  [anon:something or another]\n";
+
+  VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_multiple_reads) {
+  std::vector<TestMapInfo> expected_info;
+  std::string map_data;
+  uint64_t start = 0xa0000;
+  for (size_t i = 0; i < 10000; i++) {
+    map_data += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r--p %zx 01:20 %zu fake.so\n",
+                                            start, start + 0x1000, i, 1000 + i);
+    expected_info.emplace_back(start, start + 0x1000, PROT_READ, i, 1000 + i, "fake.so");
+  }
+
+  VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_buffer_nullptr) {
+  size_t num_calls = 0;
+  auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
+
+#if defined(__BIONIC__)
+  // Any allocations will block after this call.
+  malloc_disable();
+#endif
+
+  bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", nullptr, 10, callback);
+
+#if defined(__BIONIC__)
+  malloc_enable();
+#endif
+
+  ASSERT_FALSE(parsed);
+  EXPECT_EQ(0UL, num_calls);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_buffer_size_zero) {
+  size_t num_calls = 0;
+  auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
+
+#if defined(__BIONIC__)
+  // Any allocations will block after this call.
+  malloc_disable();
+#endif
+
+  char buffer[10];
+  bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, 0, callback);
+
+#if defined(__BIONIC__)
+  malloc_enable();
+#endif
+
+  ASSERT_FALSE(parsed);
+  EXPECT_EQ(0UL, num_calls);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_no_calls) {
+  size_t num_calls = 0;
+  auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
+
+#if defined(__BIONIC__)
+  // Any allocations will block after this call.
+  malloc_disable();
+#endif
+
+  char buffer[10];
+  bool parsed =
+      android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, sizeof(buffer), callback);
+
+#if defined(__BIONIC__)
+  malloc_enable();
+#endif
+
+  ASSERT_FALSE(parsed);
+  EXPECT_EQ(0UL, num_calls);
+}
+
+TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_could_parse) {
+  TemporaryFile tf;
+  ASSERT_TRUE(android::base::WriteStringToFd(
+      "0a0000-0c0000 rwxp 00000001 00:05 100    /fake/lib.so\n", tf.fd));
+
+  size_t num_calls = 0;
+  auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; };
+
+#if defined(__BIONIC__)
+  // Any allocations will block after this call.
+  malloc_disable();
+#endif
+
+  char buffer[39];
+  bool parsed = android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer, sizeof(buffer), callback);
+
+#if defined(__BIONIC__)
+  malloc_enable();
+#endif
+
+  ASSERT_FALSE(parsed);
+  EXPECT_EQ(0UL, num_calls);
+}
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 2ec4754..88146e9 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -82,3 +82,15 @@
         },
     },
 }
+
+cc_fuzz {
+    name: "sparse_fuzzer",
+    host_supported: false,
+    srcs: [
+        "sparse_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libsparse",
+        "liblog",
+    ],
+}
diff --git a/libsparse/output_file.cpp b/libsparse/output_file.cpp
index 5b8179f..e35cb0d 100644
--- a/libsparse/output_file.cpp
+++ b/libsparse/output_file.cpp
@@ -17,6 +17,7 @@
 #define _FILE_OFFSET_BITS 64
 #define _LARGEFILE64_SOURCE 1
 
+#include <algorithm>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <limits.h>
@@ -48,13 +49,6 @@
 #define off64_t off_t
 #endif
 
-#define min(a, b)        \
-  ({                     \
-    typeof(a) _a = (a);  \
-    typeof(b) _b = (b);  \
-    (_a < _b) ? _a : _b; \
-  })
-
 #define SPARSE_HEADER_MAJOR_VER 1
 #define SPARSE_HEADER_MINOR_VER 0
 #define SPARSE_HEADER_LEN (sizeof(sparse_header_t))
@@ -231,7 +225,7 @@
   struct output_file_gz* outgz = to_output_file_gz(out);
 
   while (len > 0) {
-    ret = gzwrite(outgz->gz_fd, data, min(len, (unsigned int)INT_MAX));
+    ret = gzwrite(outgz->gz_fd, data, std::min<unsigned int>(len, (unsigned int)INT_MAX));
     if (ret == 0) {
       error("gzwrite %s", gzerror(outgz->gz_fd, nullptr));
       return -1;
@@ -268,7 +262,7 @@
   int ret;
 
   while (off > 0) {
-    to_write = min(off, (int64_t)INT_MAX);
+    to_write = std::min(off, (int64_t)INT_MAX);
     ret = outc->write(outc->priv, nullptr, to_write);
     if (ret < 0) {
       return ret;
@@ -470,7 +464,7 @@
   }
 
   while (len) {
-    write_len = min(len, out->block_size);
+    write_len = std::min(len, out->block_size);
     ret = out->ops->write(out, out->fill_buf, write_len);
     if (ret < 0) {
       return ret;
@@ -499,6 +493,10 @@
 
 void output_file_close(struct output_file* out) {
   out->sparse_ops->write_end_chunk(out);
+  free(out->zero_buf);
+  free(out->fill_buf);
+  out->zero_buf = nullptr;
+  out->fill_buf = nullptr;
   out->ops->close(out);
 }
 
diff --git a/libsparse/sparse.cpp b/libsparse/sparse.cpp
index cb288c5..24c6379 100644
--- a/libsparse/sparse.cpp
+++ b/libsparse/sparse.cpp
@@ -188,7 +188,7 @@
                               int (*write)(void* priv, const void* data, size_t len,
                                            unsigned int block, unsigned int nr_blocks),
                               void* priv) {
-  int ret;
+  int ret = 0;
   int chunks;
   struct chunk_data chk;
   struct output_file* out;
diff --git a/libsparse/sparse_fuzzer.cpp b/libsparse/sparse_fuzzer.cpp
new file mode 100644
index 0000000..42f331f
--- /dev/null
+++ b/libsparse/sparse_fuzzer.cpp
@@ -0,0 +1,16 @@
+#include "include/sparse/sparse.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size < 2 * sizeof(wchar_t)) return 0;
+
+  int64_t blocksize = 4096;
+  struct sparse_file* file = sparse_file_new(size, blocksize);
+  if (!file) {
+    return 0;
+  }
+
+  unsigned int block = 1;
+  sparse_file_add_data(file, &data, size, block);
+  sparse_file_destroy(file);
+  return 0;
+}
diff --git a/libstats/Android.bp b/libstats/Android.bp
deleted file mode 100644
index f5ee1da..0000000
--- a/libstats/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// 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.
-//
-
-// ==========================================================
-// Native library to write stats log to statsd socket
-// ==========================================================
-cc_library {
-    name: "libstatssocket",
-    srcs: [
-        "stats_event_list.c",
-        "statsd_writer.c",
-    ],
-    host_supported: true,
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-DLIBLOG_LOG_TAG=1006",
-        "-DWRITE_TO_STATSD=1",
-        "-DWRITE_TO_LOGD=0",
-    ],
-    export_include_dirs: ["include"],
-    shared_libs: [
-        "libcutils",
-        "liblog",
-    ],
-}
diff --git a/libstats/OWNERS b/libstats/OWNERS
index ed06fbc..7855774 100644
--- a/libstats/OWNERS
+++ b/libstats/OWNERS
@@ -1,4 +1,7 @@
-bookatz@google.com
 joeo@google.com
+muhammadq@google.com
+ruchirr@google.com
+singhtejinder@google.com
+tsaichristine@google.com
 yaochen@google.com
-yanglu@google.com
+yro@google.com
diff --git a/libstats/push_compat/Android.bp b/libstats/push_compat/Android.bp
new file mode 100644
index 0000000..465c05a
--- /dev/null
+++ b/libstats/push_compat/Android.bp
@@ -0,0 +1,59 @@
+//
+// 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.
+//
+
+// =========================================================================
+// Native library that toggles between the old and new statsd socket
+// protocols. This library should only be used by DNS resolver or other
+// native modules on Q that log pushed atoms to statsd.
+// =========================================================================
+cc_defaults {
+    name: "libstatspush_compat_defaults",
+    srcs: [
+        "statsd_writer.c",
+        "stats_event_list.c",
+        "StatsEventCompat.cpp"
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-DWRITE_TO_STATSD=1",
+        "-DWRITE_TO_LOGD=0",
+    ],
+    header_libs: ["libstatssocket_headers"],
+    static_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+    ],
+}
+
+cc_library {
+    name: "libstatspush_compat",
+    defaults: ["libstatspush_compat_defaults"],
+    export_include_dirs: ["include"],
+    static_libs: ["libgtest_prod"],
+}
+
+cc_test {
+    name: "libstatspush_compat_test",
+    defaults: ["libstatspush_compat_defaults"],
+    test_suites: ["device_tests"],
+    srcs: [
+        "tests/StatsEventCompat_test.cpp",
+    ],
+    static_libs: ["libgmock"],
+}
+
diff --git a/libstats/push_compat/StatsEventCompat.cpp b/libstats/push_compat/StatsEventCompat.cpp
new file mode 100644
index 0000000..edfa070
--- /dev/null
+++ b/libstats/push_compat/StatsEventCompat.cpp
@@ -0,0 +1,221 @@
+/*
+ * 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 "include/StatsEventCompat.h"
+#include <android-base/properties.h>
+#include <android/api-level.h>
+#include <android/log.h>
+#include <dlfcn.h>
+#include <utils/SystemClock.h>
+
+using android::base::GetProperty;
+
+const static int kStatsEventTag = 1937006964;
+
+/* Checking ro.build.version.release is fragile, as the release field is
+ * an opaque string without structural guarantees. However, testing confirms
+ * that on Q devices, the property is "10," and on R, it is "R." Until
+ * android_get_device_api_level() is updated, this is the only solution.
+ *
+ * TODO(b/146019024): migrate to android_get_device_api_level()
+ */
+const bool StatsEventCompat::mPlatformAtLeastR =
+        GetProperty("ro.build.version.codename", "") == "R" ||
+        android_get_device_api_level() > __ANDROID_API_Q__;
+
+// definitions of static class variables
+bool StatsEventCompat::mAttemptedLoad = false;
+struct stats_event_api_table* StatsEventCompat::mStatsEventApi = nullptr;
+std::mutex StatsEventCompat::mLoadLock;
+
+StatsEventCompat::StatsEventCompat() : mEventQ(kStatsEventTag) {
+    // guard loading because StatsEventCompat might be called from multithreaded
+    // environment
+    {
+        std::lock_guard<std::mutex> lg(mLoadLock);
+        if (!mAttemptedLoad) {
+            void* handle = dlopen("libstatssocket.so", RTLD_NOW);
+            if (handle) {
+                mStatsEventApi = (struct stats_event_api_table*)dlsym(handle, "table");
+            } else {
+                ALOGE("dlopen failed: %s\n", dlerror());
+            }
+        }
+        mAttemptedLoad = true;
+    }
+
+    if (mStatsEventApi) {
+        mEventR = mStatsEventApi->obtain();
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << android::elapsedRealtimeNano();
+    }
+}
+
+StatsEventCompat::~StatsEventCompat() {
+    if (mStatsEventApi) mStatsEventApi->release(mEventR);
+}
+
+void StatsEventCompat::setAtomId(int32_t atomId) {
+    if (mStatsEventApi) {
+        mStatsEventApi->set_atom_id(mEventR, (uint32_t)atomId);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << atomId;
+    }
+}
+
+void StatsEventCompat::writeInt32(int32_t value) {
+    if (mStatsEventApi) {
+        mStatsEventApi->write_int32(mEventR, value);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << value;
+    }
+}
+
+void StatsEventCompat::writeInt64(int64_t value) {
+    if (mStatsEventApi) {
+        mStatsEventApi->write_int64(mEventR, value);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << value;
+    }
+}
+
+void StatsEventCompat::writeFloat(float value) {
+    if (mStatsEventApi) {
+        mStatsEventApi->write_float(mEventR, value);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << value;
+    }
+}
+
+void StatsEventCompat::writeBool(bool value) {
+    if (mStatsEventApi) {
+        mStatsEventApi->write_bool(mEventR, value);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << value;
+    }
+}
+
+void StatsEventCompat::writeByteArray(const char* buffer, size_t length) {
+    if (mStatsEventApi) {
+        mStatsEventApi->write_byte_array(mEventR, (const uint8_t*)buffer, length);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ.AppendCharArray(buffer, length);
+    }
+}
+
+void StatsEventCompat::writeString(const char* value) {
+    if (value == nullptr) value = "";
+
+    if (mStatsEventApi) {
+        mStatsEventApi->write_string8(mEventR, value);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ << value;
+    }
+}
+
+void StatsEventCompat::writeAttributionChain(const int32_t* uids, size_t numUids,
+                                             const vector<const char*>& tags) {
+    if (mStatsEventApi) {
+        mStatsEventApi->write_attribution_chain(mEventR, (const uint32_t*)uids, tags.data(),
+                                                (uint8_t)numUids);
+    } else if (!mPlatformAtLeastR) {
+        mEventQ.begin();
+        for (size_t i = 0; i < numUids; i++) {
+            mEventQ.begin();
+            mEventQ << uids[i];
+            const char* tag = tags[i] ? tags[i] : "";
+            mEventQ << tag;
+            mEventQ.end();
+        }
+        mEventQ.end();
+    }
+}
+
+void StatsEventCompat::writeKeyValuePairs(const map<int, int32_t>& int32Map,
+                                          const map<int, int64_t>& int64Map,
+                                          const map<int, const char*>& stringMap,
+                                          const map<int, float>& floatMap) {
+    if (mStatsEventApi) {
+        vector<struct key_value_pair> pairs;
+
+        for (const auto& it : int32Map) {
+            pairs.push_back({.key = it.first, .valueType = INT32_TYPE, .int32Value = it.second});
+        }
+        for (const auto& it : int64Map) {
+            pairs.push_back({.key = it.first, .valueType = INT64_TYPE, .int64Value = it.second});
+        }
+        for (const auto& it : stringMap) {
+            pairs.push_back({.key = it.first, .valueType = STRING_TYPE, .stringValue = it.second});
+        }
+        for (const auto& it : floatMap) {
+            pairs.push_back({.key = it.first, .valueType = FLOAT_TYPE, .floatValue = it.second});
+        }
+
+        mStatsEventApi->write_key_value_pairs(mEventR, pairs.data(), (uint8_t)pairs.size());
+    }
+
+    else if (!mPlatformAtLeastR) {
+        mEventQ.begin();
+        writeKeyValuePairMap(int32Map);
+        writeKeyValuePairMap(int64Map);
+        writeKeyValuePairMap(stringMap);
+        writeKeyValuePairMap(floatMap);
+        mEventQ.end();
+    }
+}
+
+template <class T>
+void StatsEventCompat::writeKeyValuePairMap(const map<int, T>& keyValuePairMap) {
+    for (const auto& it : keyValuePairMap) {
+        mEventQ.begin();
+        mEventQ << it.first;
+        mEventQ << it.second;
+        mEventQ.end();
+    }
+}
+
+// explicitly specify which types we're going to use
+template void StatsEventCompat::writeKeyValuePairMap<int32_t>(const map<int, int32_t>&);
+template void StatsEventCompat::writeKeyValuePairMap<int64_t>(const map<int, int64_t>&);
+template void StatsEventCompat::writeKeyValuePairMap<float>(const map<int, float>&);
+template void StatsEventCompat::writeKeyValuePairMap<const char*>(const map<int, const char*>&);
+
+void StatsEventCompat::addBoolAnnotation(uint8_t annotationId, bool value) {
+    if (mStatsEventApi) mStatsEventApi->add_bool_annotation(mEventR, annotationId, value);
+    // Don't do anything if on Q.
+}
+
+void StatsEventCompat::addInt32Annotation(uint8_t annotationId, int32_t value) {
+    if (mStatsEventApi) mStatsEventApi->add_int32_annotation(mEventR, annotationId, value);
+    // Don't do anything if on Q.
+}
+
+int StatsEventCompat::writeToSocket() {
+    if (mStatsEventApi) {
+        mStatsEventApi->build(mEventR);
+        return mStatsEventApi->write(mEventR);
+    }
+
+    if (!mPlatformAtLeastR) return mEventQ.write(LOG_ID_STATS);
+
+    // We reach here only if we're on R, but libstatspush_compat was unable to
+    // be loaded using dlopen.
+    return -ENOLINK;
+}
+
+bool StatsEventCompat::usesNewSchema() {
+    return mStatsEventApi != nullptr;
+}
diff --git a/libstats/push_compat/include/StatsEventCompat.h b/libstats/push_compat/include/StatsEventCompat.h
new file mode 100644
index 0000000..a8cde68
--- /dev/null
+++ b/libstats/push_compat/include/StatsEventCompat.h
@@ -0,0 +1,71 @@
+/*
+ * 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 <gtest/gtest_prod.h>
+#include <map>
+#include <mutex>
+#include <vector>
+#include "stats_event.h"
+#include "stats_event_list.h"
+
+using std::map;
+using std::vector;
+
+class StatsEventCompat {
+  public:
+    StatsEventCompat();
+    ~StatsEventCompat();
+
+    void setAtomId(int32_t atomId);
+    void writeInt32(int32_t value);
+    void writeInt64(int64_t value);
+    void writeFloat(float value);
+    void writeBool(bool value);
+    void writeByteArray(const char* buffer, size_t length);
+    void writeString(const char* value);
+
+    // Pre-condition: numUids == tags.size()
+    void writeAttributionChain(const int32_t* uids, size_t numUids,
+                               const vector<const char*>& tags);
+
+    void writeKeyValuePairs(const map<int, int32_t>& int32Map, const map<int, int64_t>& int64Map,
+                            const map<int, const char*>& stringMap,
+                            const map<int, float>& floatMap);
+
+    void addBoolAnnotation(uint8_t annotationId, bool value);
+    void addInt32Annotation(uint8_t annotationId, int32_t value);
+
+    int writeToSocket();
+
+  private:
+    // static member variables
+    const static bool mPlatformAtLeastR;
+    static bool mAttemptedLoad;
+    static std::mutex mLoadLock;
+    static struct stats_event_api_table* mStatsEventApi;
+
+    // non-static member variables
+    struct stats_event* mEventR = nullptr;
+    stats_event_list mEventQ;
+
+    template <class T>
+    void writeKeyValuePairMap(const map<int, T>& keyValuePairMap);
+
+    bool usesNewSchema();
+    FRIEND_TEST(StatsEventCompatTest, TestDynamicLoading);
+};
diff --git a/libstats/include/stats_event_list.h b/libstats/push_compat/include/stats_event_list.h
similarity index 96%
rename from libstats/include/stats_event_list.h
rename to libstats/push_compat/include/stats_event_list.h
index 845a197..b7ada0c 100644
--- a/libstats/include/stats_event_list.h
+++ b/libstats/push_compat/include/stats_event_list.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_STATS_LOG_STATS_EVENT_LIST_H
-#define ANDROID_STATS_LOG_STATS_EVENT_LIST_H
+#pragma once
 
 #include <log/log_event_list.h>
 #include <sys/uio.h>
@@ -133,7 +132,6 @@
         return *this;
     }
 
-#if defined(_USING_LIBCXX)
     stats_event_list& operator<<(const std::string& value) {
         int retval = android_log_write_string8_len(ctx, value.data(), value.length());
         if (retval < 0) {
@@ -141,7 +139,6 @@
         }
         return *this;
     }
-#endif
 
     stats_event_list& operator<<(float value) {
         int retval = android_log_write_float32(ctx, value);
@@ -203,7 +200,6 @@
         return ret >= 0;
     }
 
-#if defined(_USING_LIBCXX)
     bool AppendString(const std::string& value) {
         int retval = android_log_write_string8_len(ctx, value.data(), value.length());
         if (retval < 0) {
@@ -219,7 +215,6 @@
         }
         return ret;
     }
-#endif
 
     bool AppendFloat(float value) {
         int retval = android_log_write_float32(ctx, value);
@@ -253,4 +248,3 @@
 };
 
 #endif
-#endif  // ANDROID_STATS_LOG_STATS_EVENT_LIST_H
diff --git a/libstats/stats_event_list.c b/libstats/push_compat/stats_event_list.c
similarity index 100%
rename from libstats/stats_event_list.c
rename to libstats/push_compat/stats_event_list.c
diff --git a/libstats/statsd_writer.c b/libstats/push_compat/statsd_writer.c
similarity index 93%
rename from libstats/statsd_writer.c
rename to libstats/push_compat/statsd_writer.c
index b1c05ea..04d3b46 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/push_compat/statsd_writer.c
@@ -36,25 +36,6 @@
 #include <time.h>
 #include <unistd.h>
 
-/* branchless on many architectures. */
-#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
-
-#ifndef htole32
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define htole32(x) (x)
-#else
-#define htole32(x) __bswap_32(x)
-#endif
-#endif
-
-#ifndef htole64
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define htole64(x) (x)
-#else
-#define htole64(x) __bswap_64(x)
-#endif
-#endif
-
 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
 static atomic_int dropped = 0;
 static atomic_int log_error = 0;
@@ -120,7 +101,7 @@
             strcpy(un.sun_path, "/dev/socket/statsdw");
 
             if (TEMP_FAILURE_RETRY(
-                    connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) < 0) {
+                        connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) < 0) {
                 ret = -errno;
                 switch (ret) {
                     case -ENOTCONN:
@@ -221,14 +202,14 @@
             android_log_event_long_t buffer;
             header.id = LOG_ID_STATS;
             // store the last log error in the tag field. This tag field is not used by statsd.
-            buffer.header.tag = htole32(atomic_load(&log_error));
+            buffer.header.tag = atomic_load(&log_error);
             buffer.payload.type = EVENT_TYPE_LONG;
             // format:
             // |atom_tag|dropped_count|
             int64_t composed_long = atomic_load(&atom_tag);
             // Send 2 int32's via an int64.
             composed_long = ((composed_long << 32) | ((int64_t)snapshot));
-            buffer.payload.data = htole64(composed_long);
+            buffer.payload.data = composed_long;
 
             newVec[headerLength].iov_base = &buffer;
             newVec[headerLength].iov_len = sizeof(buffer);
diff --git a/libstats/statsd_writer.h b/libstats/push_compat/statsd_writer.h
similarity index 100%
copy from libstats/statsd_writer.h
copy to libstats/push_compat/statsd_writer.h
diff --git a/libstats/push_compat/tests/StatsEventCompat_test.cpp b/libstats/push_compat/tests/StatsEventCompat_test.cpp
new file mode 100644
index 0000000..2be24ec
--- /dev/null
+++ b/libstats/push_compat/tests/StatsEventCompat_test.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "include/StatsEventCompat.h"
+#include <android-base/properties.h>
+#include <android/api-level.h>
+#include <gtest/gtest.h>
+
+using android::base::GetProperty;
+
+/* Checking ro.build.version.release is fragile, as the release field is
+ * an opaque string without structural guarantees. However, testing confirms
+ * that on Q devices, the property is "10," and on R, it is "R." Until
+ * android_get_device_api_level() is updated, this is the only solution.
+ *
+ *
+ * TODO(b/146019024): migrate to android_get_device_api_level()
+ */
+const static bool mPlatformAtLeastR = GetProperty("ro.build.version.release", "") == "R" ||
+                                      android_get_device_api_level() > __ANDROID_API_Q__;
+
+TEST(StatsEventCompatTest, TestDynamicLoading) {
+    StatsEventCompat event;
+    EXPECT_EQ(mPlatformAtLeastR, event.usesNewSchema());
+}
diff --git a/libstats/socket/Android.bp b/libstats/socket/Android.bp
new file mode 100644
index 0000000..94c405d
--- /dev/null
+++ b/libstats/socket/Android.bp
@@ -0,0 +1,69 @@
+//
+// 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.
+//
+
+// =========================================================================
+// Native library to write stats log to statsd socket on Android R and later
+// =========================================================================
+cc_library {
+    name: "libstatssocket",
+    srcs: [
+        "stats_buffer_writer.c",
+        "stats_event.c",
+        // TODO(b/145573568): Remove stats_event_list once stats_event
+        // migration is complete.
+        "stats_event_list.c",
+        "statsd_writer.c",
+    ],
+    host_supported: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-DLIBLOG_LOG_TAG=1006",
+        "-DWRITE_TO_STATSD=1",
+        "-DWRITE_TO_LOGD=0",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+}
+
+cc_library_headers {
+    name: "libstatssocket_headers",
+    export_include_dirs: ["include"],
+    host_supported: true,
+}
+
+cc_benchmark {
+    name: "libstatssocket_benchmark",
+    srcs: [
+        "benchmark/main.cpp",
+        "benchmark/stats_event_benchmark.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    static_libs: [
+        "libstatssocket",
+    ],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libgtest_prod",
+    ],
+}
diff --git a/libmemunreachable/tests/HostMallocStub.cpp b/libstats/socket/benchmark/main.cpp
similarity index 81%
rename from libmemunreachable/tests/HostMallocStub.cpp
rename to libstats/socket/benchmark/main.cpp
index 0ef0487..5ebdf6e 100644
--- a/libmemunreachable/tests/HostMallocStub.cpp
+++ b/libstats/socket/benchmark/main.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include "bionic.h"
+#include <benchmark/benchmark.h>
 
-void malloc_disable() {}
-
-void malloc_enable() {}
+BENCHMARK_MAIN();
diff --git a/libstats/socket/benchmark/stats_event_benchmark.cpp b/libstats/socket/benchmark/stats_event_benchmark.cpp
new file mode 100644
index 0000000..b487c4d
--- /dev/null
+++ b/libstats/socket/benchmark/stats_event_benchmark.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 "benchmark/benchmark.h"
+#include "stats_event.h"
+
+static struct stats_event* constructStatsEvent() {
+    struct stats_event* event = stats_event_obtain();
+    stats_event_set_atom_id(event, 100);
+
+    // randomly sample atom size
+    for (int i = 0; i < rand() % 800; i++) {
+        stats_event_write_int32(event, i);
+    }
+
+    return event;
+}
+
+static void BM_stats_event_truncate_buffer(benchmark::State& state) {
+    while (state.KeepRunning()) {
+        struct stats_event* event = constructStatsEvent();
+        stats_event_build(event);
+        stats_event_write(event);
+        stats_event_release(event);
+    }
+}
+
+BENCHMARK(BM_stats_event_truncate_buffer);
+
+static void BM_stats_event_full_buffer(benchmark::State& state) {
+    while (state.KeepRunning()) {
+        struct stats_event* event = constructStatsEvent();
+        stats_event_truncate_buffer(event, false);
+        stats_event_build(event);
+        stats_event_write(event);
+        stats_event_release(event);
+    }
+}
+
+BENCHMARK(BM_stats_event_full_buffer);
diff --git a/libnativeloader/test/api_test.c b/libstats/socket/include/stats_buffer_writer.h
similarity index 70%
rename from libnativeloader/test/api_test.c
rename to libstats/socket/include/stats_buffer_writer.h
index e7025fd..de4a5e2 100644
--- a/libnativeloader/test/api_test.c
+++ b/libstats/socket/include/stats_buffer_writer.h
@@ -14,12 +14,16 @@
  * limitations under the License.
  */
 
-/* The main purpose of this test is to ensure this C header compiles in C, so
- * that no C++ features inadvertently leak into the C ABI. */
-#include "nativeloader/native_loader.h"
+#pragma once
 
-int main(int argc, char** argv) {
-  (void)argc;
-  (void)argv;
-  return 0;
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __CPLUSPLUS
+void stats_log_close();
+int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId);
+#ifdef __cplusplus
 }
+#endif  // __CPLUSPLUS
diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h
new file mode 100644
index 0000000..080e957
--- /dev/null
+++ b/libstats/socket/include/stats_event.h
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_STATS_LOG_STATS_EVENT_H
+#define ANDROID_STATS_LOG_STATS_EVENT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * Functionality to build and store the buffer sent over the statsd socket.
+ * This code defines and encapsulates the socket protocol.
+ *
+ * Usage:
+ *      struct stats_event* event = stats_event_obtain();
+ *
+ *      stats_event_set_atom_id(event, atomId);
+ *      stats_event_write_int32(event, 24);
+ *      stats_event_add_bool_annotation(event, 1, true); // annotations apply to the previous field
+ *      stats_event_add_int32_annotation(event, 2, 128);
+ *      stats_event_write_float(event, 2.0);
+ *
+ *      stats_event_build(event);
+ *      stats_event_write(event);
+ *      stats_event_release(event);
+ *
+ * Notes:
+ *    (a) write_<type>() and add_<type>_annotation() should be called in the order that fields
+ *        and annotations are defined in the atom.
+ *    (b) set_atom_id() can be called anytime before stats_event_write().
+ *    (c) add_<type>_annotation() calls apply to the previous field.
+ *    (d) If errors occur, stats_event_write() will write a bitmask of the errors to the socket.
+ *    (e) All strings should be encoded using UTF8.
+ */
+
+/* ERRORS */
+#define ERROR_NO_TIMESTAMP 0x1
+#define ERROR_NO_ATOM_ID 0x2
+#define ERROR_OVERFLOW 0x4
+#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
+#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
+#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
+#define ERROR_INVALID_ANNOTATION_ID 0x40
+#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
+#define ERROR_TOO_MANY_ANNOTATIONS 0x100
+#define ERROR_TOO_MANY_FIELDS 0x200
+#define ERROR_INVALID_VALUE_TYPE 0x400
+#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
+
+/* TYPE IDS */
+#define INT32_TYPE 0x00
+#define INT64_TYPE 0x01
+#define STRING_TYPE 0x02
+#define LIST_TYPE 0x03
+#define FLOAT_TYPE 0x04
+#define BOOL_TYPE 0x05
+#define BYTE_ARRAY_TYPE 0x06
+#define OBJECT_TYPE 0x07
+#define KEY_VALUE_PAIRS_TYPE 0x08
+#define ATTRIBUTION_CHAIN_TYPE 0x09
+#define ERROR_TYPE 0x0F
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __CPLUSPLUS
+
+struct stats_event;
+
+/* SYSTEM API */
+struct stats_event* stats_event_obtain();
+// The build function can be called multiple times without error. If the event
+// has been built before, this function is a no-op.
+void stats_event_build(struct stats_event* event);
+int stats_event_write(struct stats_event* event);
+void stats_event_release(struct stats_event* event);
+
+void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId);
+
+void stats_event_write_int32(struct stats_event* event, int32_t value);
+void stats_event_write_int64(struct stats_event* event, int64_t value);
+void stats_event_write_float(struct stats_event* event, float value);
+void stats_event_write_bool(struct stats_event* event, bool value);
+
+void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes);
+
+// Buf must be null-terminated.
+void stats_event_write_string8(struct stats_event* event, const char* value);
+
+// Tags must be null-terminated.
+void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
+                                         const char* const* tags, uint8_t numNodes);
+
+/* key_value_pair struct can be constructed as follows:
+ *    struct key_value_pair pair = {.key = key, .valueType = STRING_TYPE,
+ *                                  .stringValue = buf};
+ */
+struct key_value_pair {
+    int32_t key;
+    uint8_t valueType;  // expected to be INT32_TYPE, INT64_TYPE, FLOAT_TYPE, or STRING_TYPE
+    union {
+        int32_t int32Value;
+        int64_t int64Value;
+        float floatValue;
+        const char* stringValue;  // must be null terminated
+    };
+};
+
+void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs,
+                                       uint8_t numPairs);
+
+void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value);
+void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId,
+                                      int32_t value);
+
+uint32_t stats_event_get_atom_id(struct stats_event* event);
+// Size is an output parameter.
+uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size);
+uint32_t stats_event_get_errors(struct stats_event* event);
+
+// This table is used by StatsEventCompat to access the stats_event API.
+struct stats_event_api_table {
+    struct stats_event* (*obtain)(void);
+    void (*build)(struct stats_event*);
+    int (*write)(struct stats_event*);
+    void (*release)(struct stats_event*);
+    void (*set_atom_id)(struct stats_event*, uint32_t);
+    void (*write_int32)(struct stats_event*, int32_t);
+    void (*write_int64)(struct stats_event*, int64_t);
+    void (*write_float)(struct stats_event*, float);
+    void (*write_bool)(struct stats_event*, bool);
+    void (*write_byte_array)(struct stats_event*, const uint8_t*, size_t);
+    void (*write_string8)(struct stats_event*, const char*);
+    void (*write_attribution_chain)(struct stats_event*, const uint32_t*, const char* const*,
+                                    uint8_t);
+    void (*write_key_value_pairs)(struct stats_event*, struct key_value_pair*, uint8_t);
+    void (*add_bool_annotation)(struct stats_event*, uint8_t, bool);
+    void (*add_int32_annotation)(struct stats_event*, uint8_t, int32_t);
+    uint32_t (*get_atom_id)(struct stats_event*);
+    uint8_t* (*get_buffer)(struct stats_event*, size_t*);
+    uint32_t (*get_errors)(struct stats_event*);
+};
+
+// exposed for benchmarking only
+void stats_event_truncate_buffer(struct stats_event* event, bool truncate);
+
+#ifdef __cplusplus
+}
+#endif  // __CPLUSPLUS
+
+#endif  // ANDROID_STATS_LOG_STATS_EVENT_H
diff --git a/libstats/include/stats_event_list.h b/libstats/socket/include/stats_event_list.h
similarity index 95%
copy from libstats/include/stats_event_list.h
copy to libstats/socket/include/stats_event_list.h
index 845a197..7a26536 100644
--- a/libstats/include/stats_event_list.h
+++ b/libstats/socket/include/stats_event_list.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_STATS_LOG_STATS_EVENT_LIST_H
-#define ANDROID_STATS_LOG_STATS_EVENT_LIST_H
+#pragma once
 
 #include <log/log_event_list.h>
 #include <sys/uio.h>
@@ -25,11 +24,9 @@
 #endif
 void reset_log_context(android_log_context ctx);
 int write_to_logger(android_log_context context, log_id_t id);
-void note_log_drop(int error, int atom_tag);
+void note_log_drop(int error, int atomId);
 void stats_log_close();
 int android_log_write_char_array(android_log_context ctx, const char* value, size_t len);
-extern int (*write_to_statsd)(struct iovec* vec, size_t nr);
-
 #ifdef __cplusplus
 }
 #endif
@@ -133,7 +130,6 @@
         return *this;
     }
 
-#if defined(_USING_LIBCXX)
     stats_event_list& operator<<(const std::string& value) {
         int retval = android_log_write_string8_len(ctx, value.data(), value.length());
         if (retval < 0) {
@@ -141,7 +137,6 @@
         }
         return *this;
     }
-#endif
 
     stats_event_list& operator<<(float value) {
         int retval = android_log_write_float32(ctx, value);
@@ -203,7 +198,6 @@
         return ret >= 0;
     }
 
-#if defined(_USING_LIBCXX)
     bool AppendString(const std::string& value) {
         int retval = android_log_write_string8_len(ctx, value.data(), value.length());
         if (retval < 0) {
@@ -219,7 +213,6 @@
         }
         return ret;
     }
-#endif
 
     bool AppendFloat(float value) {
         int retval = android_log_write_float32(ctx, value);
@@ -253,4 +246,3 @@
 };
 
 #endif
-#endif  // ANDROID_STATS_LOG_STATS_EVENT_LIST_H
diff --git a/libstats/socket/stats_buffer_writer.c b/libstats/socket/stats_buffer_writer.c
new file mode 100644
index 0000000..c5c591d
--- /dev/null
+++ b/libstats/socket/stats_buffer_writer.c
@@ -0,0 +1,130 @@
+/*
+ * 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 "include/stats_buffer_writer.h"
+#ifdef __ANDROID__
+#include <cutils/properties.h>
+#endif
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include "statsd_writer.h"
+
+static const uint32_t kStatsEventTag = 1937006964;
+
+extern struct android_log_transport_write statsdLoggerWrite;
+
+static int __write_to_statsd_init(struct iovec* vec, size_t nr);
+static int (*__write_to_statsd)(struct iovec* vec, size_t nr) = __write_to_statsd_init;
+
+void note_log_drop(int error, int atomId) {
+    statsdLoggerWrite.noteDrop(error, atomId);
+}
+
+void stats_log_close() {
+    statsd_writer_init_lock();
+    __write_to_statsd = __write_to_statsd_init;
+    if (statsdLoggerWrite.close) {
+        (*statsdLoggerWrite.close)();
+    }
+    statsd_writer_init_unlock();
+}
+
+int write_buffer_to_statsd(void* buffer, size_t size, uint32_t atomId) {
+    int ret = 1;
+
+#ifdef __ANDROID__
+    bool statsdEnabled = property_get_bool("ro.statsd.enable", true);
+#else
+    bool statsdEnabled = false;
+#endif
+
+    if (statsdEnabled) {
+        struct iovec vecs[2];
+        vecs[0].iov_base = (void*)&kStatsEventTag;
+        vecs[0].iov_len = sizeof(kStatsEventTag);
+        vecs[1].iov_base = buffer;
+        vecs[1].iov_len = size;
+
+        ret = __write_to_statsd(vecs, 2);
+
+        if (ret < 0) {
+            note_log_drop(ret, atomId);
+        }
+    }
+
+    return ret;
+}
+
+static int __write_to_stats_daemon(struct iovec* vec, size_t nr) {
+    int save_errno;
+    struct timespec ts;
+    size_t len, i;
+
+    for (len = i = 0; i < nr; ++i) {
+        len += vec[i].iov_len;
+    }
+    if (!len) {
+        return -EINVAL;
+    }
+
+    save_errno = errno;
+#if defined(__ANDROID__)
+    clock_gettime(CLOCK_REALTIME, &ts);
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    ts.tv_sec = tv.tv_sec;
+    ts.tv_nsec = tv.tv_usec * 1000;
+#endif
+
+    int ret = (int)(*statsdLoggerWrite.write)(&ts, vec, nr);
+    errno = save_errno;
+    return ret;
+}
+
+static int __write_to_statsd_initialize_locked() {
+    if (!statsdLoggerWrite.open || ((*statsdLoggerWrite.open)() < 0)) {
+        if (statsdLoggerWrite.close) {
+            (*statsdLoggerWrite.close)();
+            return -ENODEV;
+        }
+    }
+    return 1;
+}
+
+static int __write_to_statsd_init(struct iovec* vec, size_t nr) {
+    int ret, save_errno = errno;
+
+    statsd_writer_init_lock();
+
+    if (__write_to_statsd == __write_to_statsd_init) {
+        ret = __write_to_statsd_initialize_locked();
+        if (ret < 0) {
+            statsd_writer_init_unlock();
+            errno = save_errno;
+            return ret;
+        }
+
+        __write_to_statsd = __write_to_stats_daemon;
+    }
+
+    statsd_writer_init_unlock();
+
+    ret = __write_to_statsd(vec, nr);
+    errno = save_errno;
+    return ret;
+}
diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c
new file mode 100644
index 0000000..15039c6
--- /dev/null
+++ b/libstats/socket/stats_event.c
@@ -0,0 +1,354 @@
+/*
+ * 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 "include/stats_event.h"
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "stats_buffer_writer.h"
+
+#define LOGGER_ENTRY_MAX_PAYLOAD 4068
+// Max payload size is 4 bytes less as 4 bytes are reserved for stats_eventTag.
+// See android_util_Stats_Log.cpp
+#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - 4)
+
+/* POSITIONS */
+#define POS_NUM_ELEMENTS 1
+#define POS_TIMESTAMP (POS_NUM_ELEMENTS + sizeof(uint8_t))
+#define POS_ATOM_ID (POS_TIMESTAMP + sizeof(uint8_t) + sizeof(uint64_t))
+#define POS_FIRST_FIELD (POS_ATOM_ID + sizeof(uint8_t) + sizeof(uint32_t))
+
+/* LIMITS */
+#define MAX_ANNOTATION_COUNT 15
+#define MAX_BYTE_VALUE 127  // parsing side requires that lengths fit in 7 bits
+
+// The stats_event struct holds the serialized encoding of an event
+// within a buf. Also includes other required fields.
+struct stats_event {
+    uint8_t* buf;
+    size_t lastFieldPos;  // location of last field within the buf
+    size_t size;          // number of valid bytes within buffer
+    uint32_t numElements;
+    uint32_t atomId;
+    uint32_t errors;
+    bool truncate;
+    bool built;
+};
+
+static int64_t get_elapsed_realtime_ns() {
+    struct timespec t;
+    t.tv_sec = t.tv_nsec = 0;
+    clock_gettime(CLOCK_BOOTTIME, &t);
+    return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;
+}
+
+struct stats_event* stats_event_obtain() {
+    struct stats_event* event = malloc(sizeof(struct stats_event));
+    event->buf = (uint8_t*)calloc(MAX_EVENT_PAYLOAD, 1);
+    event->buf[0] = OBJECT_TYPE;
+    event->atomId = 0;
+    event->errors = 0;
+    event->truncate = true;  // truncate for both pulled and pushed atoms
+    event->built = false;
+
+    // place the timestamp
+    uint64_t timestampNs = get_elapsed_realtime_ns();
+    event->buf[POS_TIMESTAMP] = INT64_TYPE;
+    memcpy(&event->buf[POS_TIMESTAMP + sizeof(uint8_t)], &timestampNs, sizeof(timestampNs));
+
+    event->numElements = 1;
+    event->lastFieldPos = 0;  // 0 since we haven't written a field yet
+    event->size = POS_FIRST_FIELD;
+
+    return event;
+}
+
+void stats_event_release(struct stats_event* event) {
+    free(event->buf);
+    free(event);
+}
+
+void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId) {
+    event->atomId = atomId;
+    event->buf[POS_ATOM_ID] = INT32_TYPE;
+    memcpy(&event->buf[POS_ATOM_ID + sizeof(uint8_t)], &atomId, sizeof(atomId));
+    event->numElements++;
+}
+
+// Side-effect: modifies event->errors if the buffer would overflow
+static bool overflows(struct stats_event* event, size_t size) {
+    if (event->size + size > MAX_EVENT_PAYLOAD) {
+        event->errors |= ERROR_OVERFLOW;
+        return true;
+    }
+    return false;
+}
+
+// Side-effect: all append functions increment event->size if there is
+// sufficient space within the buffer to place the value
+static void append_byte(struct stats_event* event, uint8_t value) {
+    if (!overflows(event, sizeof(value))) {
+        event->buf[event->size] = value;
+        event->size += sizeof(value);
+    }
+}
+
+static void append_bool(struct stats_event* event, bool value) {
+    append_byte(event, (uint8_t)value);
+}
+
+static void append_int32(struct stats_event* event, int32_t value) {
+    if (!overflows(event, sizeof(value))) {
+        memcpy(&event->buf[event->size], &value, sizeof(value));
+        event->size += sizeof(value);
+    }
+}
+
+static void append_int64(struct stats_event* event, int64_t value) {
+    if (!overflows(event, sizeof(value))) {
+        memcpy(&event->buf[event->size], &value, sizeof(value));
+        event->size += sizeof(value);
+    }
+}
+
+static void append_float(struct stats_event* event, float value) {
+    if (!overflows(event, sizeof(value))) {
+        memcpy(&event->buf[event->size], &value, sizeof(value));
+        event->size += sizeof(float);
+    }
+}
+
+static void append_byte_array(struct stats_event* event, const uint8_t* buf, size_t size) {
+    if (!overflows(event, size)) {
+        memcpy(&event->buf[event->size], buf, size);
+        event->size += size;
+    }
+}
+
+// Side-effect: modifies event->errors if buf is not properly null-terminated
+static void append_string(struct stats_event* event, const char* buf) {
+    size_t size = strnlen(buf, MAX_EVENT_PAYLOAD);
+    if (size == MAX_EVENT_PAYLOAD) {
+        event->errors |= ERROR_STRING_NOT_NULL_TERMINATED;
+        return;
+    }
+
+    append_int32(event, size);
+    append_byte_array(event, (uint8_t*)buf, size);
+}
+
+static void start_field(struct stats_event* event, uint8_t typeId) {
+    event->lastFieldPos = event->size;
+    append_byte(event, typeId);
+    event->numElements++;
+}
+
+void stats_event_write_int32(struct stats_event* event, int32_t value) {
+    if (event->errors) return;
+
+    start_field(event, INT32_TYPE);
+    append_int32(event, value);
+}
+
+void stats_event_write_int64(struct stats_event* event, int64_t value) {
+    if (event->errors) return;
+
+    start_field(event, INT64_TYPE);
+    append_int64(event, value);
+}
+
+void stats_event_write_float(struct stats_event* event, float value) {
+    if (event->errors) return;
+
+    start_field(event, FLOAT_TYPE);
+    append_float(event, value);
+}
+
+void stats_event_write_bool(struct stats_event* event, bool value) {
+    if (event->errors) return;
+
+    start_field(event, BOOL_TYPE);
+    append_bool(event, value);
+}
+
+void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes) {
+    if (event->errors) return;
+
+    start_field(event, BYTE_ARRAY_TYPE);
+    append_int32(event, numBytes);
+    append_byte_array(event, buf, numBytes);
+}
+
+// Value is assumed to be encoded using UTF8
+void stats_event_write_string8(struct stats_event* event, const char* value) {
+    if (event->errors) return;
+
+    start_field(event, STRING_TYPE);
+    append_string(event, value);
+}
+
+// Tags are assumed to be encoded using UTF8
+void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
+                                         const char* const* tags, uint8_t numNodes) {
+    if (numNodes > MAX_BYTE_VALUE) event->errors |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
+    if (event->errors) return;
+
+    start_field(event, ATTRIBUTION_CHAIN_TYPE);
+    append_byte(event, numNodes);
+
+    for (uint8_t i = 0; i < numNodes; i++) {
+        append_int32(event, uids[i]);
+        append_string(event, tags[i]);
+    }
+}
+
+void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs,
+                                       uint8_t numPairs) {
+    if (numPairs > MAX_BYTE_VALUE) event->errors |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
+    if (event->errors) return;
+
+    start_field(event, KEY_VALUE_PAIRS_TYPE);
+    append_byte(event, numPairs);
+
+    for (uint8_t i = 0; i < numPairs; i++) {
+        append_int32(event, pairs[i].key);
+        append_byte(event, pairs[i].valueType);
+        switch (pairs[i].valueType) {
+            case INT32_TYPE:
+                append_int32(event, pairs[i].int32Value);
+                break;
+            case INT64_TYPE:
+                append_int64(event, pairs[i].int64Value);
+                break;
+            case FLOAT_TYPE:
+                append_float(event, pairs[i].floatValue);
+                break;
+            case STRING_TYPE:
+                append_string(event, pairs[i].stringValue);
+                break;
+            default:
+                event->errors |= ERROR_INVALID_VALUE_TYPE;
+                return;
+        }
+    }
+}
+
+// Side-effect: modifies event->errors if field has too many annotations
+static void increment_annotation_count(struct stats_event* event) {
+    uint8_t fieldType = event->buf[event->lastFieldPos] & 0x0F;
+    uint32_t oldAnnotationCount = (event->buf[event->lastFieldPos] & 0xF0) >> 4;
+    uint32_t newAnnotationCount = oldAnnotationCount + 1;
+
+    if (newAnnotationCount > MAX_ANNOTATION_COUNT) {
+        event->errors |= ERROR_TOO_MANY_ANNOTATIONS;
+        return;
+    }
+
+    event->buf[event->lastFieldPos] = (((uint8_t)newAnnotationCount << 4) & 0xF0) | fieldType;
+}
+
+void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value) {
+    if (event->lastFieldPos == 0) event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+    if (annotationId > MAX_BYTE_VALUE) event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE;
+    if (event->errors) return;
+
+    append_byte(event, annotationId);
+    append_byte(event, BOOL_TYPE);
+    append_bool(event, value);
+    increment_annotation_count(event);
+}
+
+void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId,
+                                      int32_t value) {
+    if (event->lastFieldPos == 0) event->errors |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+    if (annotationId > MAX_BYTE_VALUE) event->errors |= ERROR_ANNOTATION_ID_TOO_LARGE;
+    if (event->errors) return;
+
+    append_byte(event, annotationId);
+    append_byte(event, INT32_TYPE);
+    append_int32(event, value);
+    increment_annotation_count(event);
+}
+
+uint32_t stats_event_get_atom_id(struct stats_event* event) {
+    return event->atomId;
+}
+
+uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size) {
+    if (size) *size = event->size;
+    return event->buf;
+}
+
+uint32_t stats_event_get_errors(struct stats_event* event) {
+    return event->errors;
+}
+
+void stats_event_truncate_buffer(struct stats_event* event, bool truncate) {
+    event->truncate = truncate;
+}
+
+void stats_event_build(struct stats_event* event) {
+    if (event->built) return;
+
+    if (event->atomId == 0) event->errors |= ERROR_NO_ATOM_ID;
+
+    if (event->numElements > MAX_BYTE_VALUE) {
+        event->errors |= ERROR_TOO_MANY_FIELDS;
+    } else {
+        event->buf[POS_NUM_ELEMENTS] = event->numElements;
+    }
+
+    // If there are errors, rewrite buffer.
+    if (event->errors) {
+        event->buf[POS_NUM_ELEMENTS] = 3;
+        event->buf[POS_FIRST_FIELD] = ERROR_TYPE;
+        memcpy(&event->buf[POS_FIRST_FIELD + sizeof(uint8_t)], &event->errors,
+               sizeof(event->errors));
+        event->size = POS_FIRST_FIELD + sizeof(uint8_t) + sizeof(uint32_t);
+    }
+
+    // Truncate the buffer to the appropriate length in order to limit our
+    // memory usage.
+    if (event->truncate) event->buf = (uint8_t*)realloc(event->buf, event->size);
+
+    event->built = true;
+}
+
+int stats_event_write(struct stats_event* event) {
+    stats_event_build(event);
+    return write_buffer_to_statsd(&event->buf, event->size, event->atomId);
+}
+
+struct stats_event_api_table table = {
+        stats_event_obtain,
+        stats_event_build,
+        stats_event_write,
+        stats_event_release,
+        stats_event_set_atom_id,
+        stats_event_write_int32,
+        stats_event_write_int64,
+        stats_event_write_float,
+        stats_event_write_bool,
+        stats_event_write_byte_array,
+        stats_event_write_string8,
+        stats_event_write_attribution_chain,
+        stats_event_write_key_value_pairs,
+        stats_event_add_bool_annotation,
+        stats_event_add_int32_annotation,
+        stats_event_get_atom_id,
+        stats_event_get_buffer,
+        stats_event_get_errors,
+};
diff --git a/libstats/socket/stats_event_list.c b/libstats/socket/stats_event_list.c
new file mode 100644
index 0000000..661a223
--- /dev/null
+++ b/libstats/socket/stats_event_list.c
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+#include "include/stats_event_list.h"
+
+#include <string.h>
+#include <sys/time.h>
+#include "stats_buffer_writer.h"
+
+#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
+
+typedef struct {
+    uint32_t tag;
+    unsigned pos;                                    /* Read/write position into buffer */
+    unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements   */
+    unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1];  /* pos for list counter */
+    unsigned list_nest_depth;
+    unsigned len; /* Length or raw buffer. */
+    bool overflow;
+    bool list_stop; /* next call decrement list_nest_depth and issue a stop */
+    enum {
+        kAndroidLoggerRead = 1,
+        kAndroidLoggerWrite = 2,
+    } read_write_flag;
+    uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
+} android_log_context_internal;
+
+// Similar to create_android_logger(), but instead of allocation a new buffer,
+// this function resets the buffer for resuse.
+void reset_log_context(android_log_context ctx) {
+    if (!ctx) {
+        return;
+    }
+    android_log_context_internal* context = (android_log_context_internal*)(ctx);
+    uint32_t tag = context->tag;
+    memset(context, 0, sizeof(android_log_context_internal));
+
+    context->tag = tag;
+    context->read_write_flag = kAndroidLoggerWrite;
+    size_t needed = sizeof(uint8_t) + sizeof(uint8_t);
+    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
+        context->overflow = true;
+    }
+    /* Everything is a list */
+    context->storage[context->pos + 0] = EVENT_TYPE_LIST;
+    context->list[0] = context->pos + 1;
+    context->pos += needed;
+}
+
+int stats_write_list(android_log_context ctx) {
+    android_log_context_internal* context;
+    const char* msg;
+    ssize_t len;
+
+    context = (android_log_context_internal*)(ctx);
+    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
+        return -EBADF;
+    }
+
+    if (context->list_nest_depth) {
+        return -EIO;
+    }
+
+    /* NB: if there was overflow, then log is truncated. Nothing reported */
+    context->storage[1] = context->count[0];
+    len = context->len = context->pos;
+    msg = (const char*)context->storage;
+    /* it's not a list */
+    if (context->count[0] <= 1) {
+        len -= sizeof(uint8_t) + sizeof(uint8_t);
+        if (len < 0) {
+            len = 0;
+        }
+        msg += sizeof(uint8_t) + sizeof(uint8_t);
+    }
+
+    return write_buffer_to_statsd((void*)msg, len, 0);
+}
+
+int write_to_logger(android_log_context ctx, log_id_t id) {
+    int retValue = 0;
+
+    if (WRITE_TO_LOGD) {
+        retValue = android_log_write_list(ctx, id);
+    }
+
+    if (WRITE_TO_STATSD) {
+        // log_event_list's cast operator is overloaded.
+        int ret = stats_write_list(ctx);
+        // In debugging phase, we may write to both logd and statsd. Prefer to
+        // return statsd socket write error code here.
+        if (ret < 0) {
+            retValue = ret;
+        }
+    }
+
+    return retValue;
+}
+
+static inline void copy4LE(uint8_t* buf, uint32_t val) {
+    buf[0] = val & 0xFF;
+    buf[1] = (val >> 8) & 0xFF;
+    buf[2] = (val >> 16) & 0xFF;
+    buf[3] = (val >> 24) & 0xFF;
+}
+
+// Note: this function differs from android_log_write_string8_len in that the length passed in
+// should be treated as actual length and not max length.
+int android_log_write_char_array(android_log_context ctx, const char* value, size_t actual_len) {
+    size_t needed;
+    ssize_t len = actual_len;
+    android_log_context_internal* context;
+
+    context = (android_log_context_internal*)ctx;
+    if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
+        return -EBADF;
+    }
+    if (context->overflow) {
+        return -EIO;
+    }
+    if (!value) {
+        value = "";
+        len = 0;
+    }
+    needed = sizeof(uint8_t) + sizeof(int32_t) + len;
+    if ((context->pos + needed) > MAX_EVENT_PAYLOAD) {
+        /* Truncate string for delivery */
+        len = MAX_EVENT_PAYLOAD - context->pos - 1 - sizeof(int32_t);
+        if (len <= 0) {
+            context->overflow = true;
+            return -EIO;
+        }
+    }
+    context->count[context->list_nest_depth]++;
+    context->storage[context->pos + 0] = EVENT_TYPE_STRING;
+    copy4LE(&context->storage[context->pos + 1], len);
+    if (len) {
+        memcpy(&context->storage[context->pos + 5], value, len);
+    }
+    context->pos += needed;
+    return len;
+}
diff --git a/libstats/statsd_writer.c b/libstats/socket/statsd_writer.c
similarity index 93%
copy from libstats/statsd_writer.c
copy to libstats/socket/statsd_writer.c
index b1c05ea..04d3b46 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/socket/statsd_writer.c
@@ -36,25 +36,6 @@
 #include <time.h>
 #include <unistd.h>
 
-/* branchless on many architectures. */
-#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
-
-#ifndef htole32
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define htole32(x) (x)
-#else
-#define htole32(x) __bswap_32(x)
-#endif
-#endif
-
-#ifndef htole64
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define htole64(x) (x)
-#else
-#define htole64(x) __bswap_64(x)
-#endif
-#endif
-
 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
 static atomic_int dropped = 0;
 static atomic_int log_error = 0;
@@ -120,7 +101,7 @@
             strcpy(un.sun_path, "/dev/socket/statsdw");
 
             if (TEMP_FAILURE_RETRY(
-                    connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) < 0) {
+                        connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) < 0) {
                 ret = -errno;
                 switch (ret) {
                     case -ENOTCONN:
@@ -221,14 +202,14 @@
             android_log_event_long_t buffer;
             header.id = LOG_ID_STATS;
             // store the last log error in the tag field. This tag field is not used by statsd.
-            buffer.header.tag = htole32(atomic_load(&log_error));
+            buffer.header.tag = atomic_load(&log_error);
             buffer.payload.type = EVENT_TYPE_LONG;
             // format:
             // |atom_tag|dropped_count|
             int64_t composed_long = atomic_load(&atom_tag);
             // Send 2 int32's via an int64.
             composed_long = ((composed_long << 32) | ((int64_t)snapshot));
-            buffer.payload.data = htole64(composed_long);
+            buffer.payload.data = composed_long;
 
             newVec[headerLength].iov_base = &buffer;
             newVec[headerLength].iov_len = sizeof(buffer);
diff --git a/libstats/statsd_writer.h b/libstats/socket/statsd_writer.h
similarity index 100%
rename from libstats/statsd_writer.h
rename to libstats/socket/statsd_writer.h
diff --git a/libsync/Android.bp b/libsync/Android.bp
index e56f8ba..c996e1b 100644
--- a/libsync/Android.bp
+++ b/libsync/Android.bp
@@ -23,6 +23,7 @@
 cc_library {
     name: "libsync",
     recovery_available: true,
+    native_bridge_supported: true,
     defaults: ["libsync_defaults"],
 }
 
diff --git a/libsync/libsync.map.txt b/libsync/libsync.map.txt
index 53bb07a..91c3528 100644
--- a/libsync/libsync.map.txt
+++ b/libsync/libsync.map.txt
@@ -19,10 +19,10 @@
     sync_merge; # introduced=26
     sync_file_info; # introduced=26
     sync_file_info_free; # introduced=26
-    sync_wait; # vndk
-    sync_fence_info; # vndk
-    sync_pt_info; # vndk
-    sync_fence_info_free; # vndk
+    sync_wait; # llndk
+    sync_fence_info; # llndk
+    sync_pt_info; # llndk
+    sync_fence_info_free; # llndk
   local:
     *;
 };
diff --git a/libsystem/Android.bp b/libsystem/Android.bp
index 2e22b43..b265b61 100644
--- a/libsystem/Android.bp
+++ b/libsystem/Android.bp
@@ -3,6 +3,7 @@
     vendor_available: true,
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
 
     target: {
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
index da5d86c..ccda5d1 100644
--- a/libsysutils/Android.bp
+++ b/libsysutils/Android.bp
@@ -26,6 +26,19 @@
     ],
 
     export_include_dirs: ["include"],
+
+    tidy: true,
+    tidy_checks: [
+        "-*",
+        "cert-*",
+        "clang-analyzer-security*",
+        "android-*",
+    ],
+    tidy_checks_as_errors: [
+        "cert-*",
+        "clang-analyzer-security*",
+        "android-*",
+    ],
 }
 
 cc_test {
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 9dc2699..2351afa 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -24,7 +24,6 @@
 #include <linux/if_link.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_log.h>
-#include <linux/netfilter_ipv4/ipt_ULOG.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <net/if.h>
@@ -39,9 +38,29 @@
 const int LOCAL_QLOG_NL_EVENT = 112;
 const int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET;
 
+/* From deprecated ipt_ULOG.h to parse QLOG_NL_EVENT. */
+#define ULOG_MAC_LEN 80
+#define ULOG_PREFIX_LEN 32
+typedef struct ulog_packet_msg {
+    unsigned long mark;
+    long timestamp_sec;
+    long timestamp_usec;
+    unsigned int hook;
+    char indev_name[IFNAMSIZ];
+    char outdev_name[IFNAMSIZ];
+    size_t data_len;
+    char prefix[ULOG_PREFIX_LEN];
+    unsigned char mac_len;
+    unsigned char mac[ULOG_MAC_LEN];
+    unsigned char payload[0];
+} ulog_packet_msg_t;
+
+#include <android-base/parseint.h>
 #include <log/log.h>
 #include <sysutils/NetlinkEvent.h>
 
+using android::base::ParseInt;
+
 NetlinkEvent::NetlinkEvent() {
     mAction = Action::kUnknown;
     memset(mParams, 0, sizeof(mParams));
@@ -301,8 +320,9 @@
         raw = (char*)nlAttrData(payload);
     }
 
-    char* hex = (char*) calloc(1, 5 + (len * 2));
-    strcpy(hex, "HEX=");
+    size_t hexSize = 5 + (len * 2);
+    char* hex = (char*)calloc(1, hexSize);
+    strlcpy(hex, "HEX=", hexSize);
     for (int i = 0; i < len; i++) {
         hex[4 + (i * 2)] = "0123456789abcdef"[(raw[i] >> 4) & 0xf];
         hex[5 + (i * 2)] = "0123456789abcdef"[raw[i] & 0xf];
@@ -474,23 +494,20 @@
         struct nd_opt_rdnss *rndss_opt = (struct nd_opt_rdnss *) opthdr;
         const uint32_t lifetime = ntohl(rndss_opt->nd_opt_rdnss_lifetime);
 
-        // Construct "SERVERS=<comma-separated string of DNS addresses>".
-        static const char kServerTag[] = "SERVERS=";
-        static const size_t kTagLength = strlen(kServerTag);
+        // Construct a comma-separated string of DNS addresses.
         // Reserve sufficient space for an IPv6 link-local address: all but the
         // last address are followed by ','; the last is followed by '\0'.
         static const size_t kMaxSingleAddressLength =
                 INET6_ADDRSTRLEN + strlen("%") + IFNAMSIZ + strlen(",");
-        const size_t bufsize = kTagLength + numaddrs * kMaxSingleAddressLength;
+        const size_t bufsize = numaddrs * kMaxSingleAddressLength;
         char *buf = (char *) malloc(bufsize);
         if (!buf) {
             SLOGE("RDNSS option: out of memory\n");
             return false;
         }
-        strcpy(buf, kServerTag);
-        size_t pos = kTagLength;
 
         struct in6_addr *addrs = (struct in6_addr *) (rndss_opt + 1);
+        size_t pos = 0;
         for (int i = 0; i < numaddrs; i++) {
             if (i > 0) {
                 buf[pos++] = ',';
@@ -508,7 +525,8 @@
         mSubsystem = strdup("net");
         asprintf(&mParams[0], "INTERFACE=%s", ifname);
         asprintf(&mParams[1], "LIFETIME=%u", lifetime);
-        mParams[2] = buf;
+        asprintf(&mParams[2], "SERVERS=%s", buf);
+        free(buf);
     } else if (opthdr->nd_opt_type == ND_OPT_DNSSL) {
         // TODO: support DNSSL.
     } else {
@@ -634,7 +652,9 @@
                 else if (!strcmp(a, "change"))
                     mAction = Action::kChange;
             } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != nullptr) {
-                mSeq = atoi(a);
+                if (!ParseInt(a, &mSeq)) {
+                    SLOGE("NetlinkEvent::parseAsciiNetlinkMessage: failed to parse SEQNUM=%s", a);
+                }
             } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != nullptr) {
                 mSubsystem = strdup(a);
             } else if (param_idx < NL_PARAMS_MAX) {
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index b7650a1..9cd3d65 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -77,6 +77,7 @@
     ],
 
     cflags: [
+        "-DDEXFILE_SUPPORT",
         "-Wexit-time-destructors",
     ],
 
@@ -89,20 +90,18 @@
             ],
         },
         vendor: {
-            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
+            cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: [
                 "DexFile.cpp",
-                "DexFiles.cpp",
             ],
             exclude_shared_libs: [
                 "libdexfile_support",
             ],
         },
         recovery: {
-            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
+            cflags: ["-UDEXFILE_SUPPORT"],
             exclude_srcs: [
                 "DexFile.cpp",
-                "DexFiles.cpp",
             ],
             exclude_shared_libs: [
                 "libdexfile_support",
@@ -125,10 +124,6 @@
         },
     },
 
-    whole_static_libs: [
-        "libdemangle"
-    ],
-
     static_libs: [
         "libprocinfo",
     ],
@@ -157,10 +152,11 @@
     shared_libs: [
         "libunwindstack",
     ],
+    relative_install_path: "libunwindstack_test",
 }
 
-cc_test {
-    name: "libunwindstack_test",
+cc_defaults {
+    name: "libunwindstack_testlib_flags",
     defaults: ["libunwindstack_flags"],
 
     srcs: [
@@ -184,8 +180,9 @@
         "tests/ElfInterfaceTest.cpp",
         "tests/ElfTest.cpp",
         "tests/ElfTestUtils.cpp",
+        "tests/IsolatedSettings.cpp",
         "tests/JitDebugTest.cpp",
-        "tests/LocalUnwinderTest.cpp",
+        "tests/LocalUpdatableMapsTest.cpp",
         "tests/LogFake.cpp",
         "tests/MapInfoCreateMemoryTest.cpp",
         "tests/MapInfoGetBuildIDTest.cpp",
@@ -213,6 +210,7 @@
         "tests/UnwindOfflineTest.cpp",
         "tests/UnwindTest.cpp",
         "tests/UnwinderTest.cpp",
+        "tests/VerifyBionicTerminationTest.cpp",
     ],
 
     cflags: [
@@ -240,23 +238,45 @@
         "tests/files/offline/bad_eh_frame_hdr_arm64/*",
         "tests/files/offline/debug_frame_first_x86/*",
         "tests/files/offline/debug_frame_load_bias_arm/*",
+        "tests/files/offline/eh_frame_bias_x86/*",
         "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
+        "tests/files/offline/invalid_elf_offset_arm/*",
         "tests/files/offline/jit_debug_arm/*",
         "tests/files/offline/jit_debug_x86/*",
         "tests/files/offline/jit_map_arm/*",
         "tests/files/offline/gnu_debugdata_arm/*",
+        "tests/files/offline/load_bias_different_section_bias_arm64/*",
+        "tests/files/offline/load_bias_ro_rx_x86_64/*",
         "tests/files/offline/offset_arm/*",
         "tests/files/offline/shared_lib_in_apk_arm64/*",
         "tests/files/offline/shared_lib_in_apk_memory_only_arm64/*",
         "tests/files/offline/shared_lib_in_apk_single_map_arm64/*",
+        "tests/files/offline/signal_load_bias_arm/*",
         "tests/files/offline/straddle_arm/*",
         "tests/files/offline/straddle_arm64/*",
     ],
+}
+
+cc_test {
+    name: "libunwindstack_test",
+    defaults: ["libunwindstack_testlib_flags"],
+    isolated: true,
+
+    srcs: [
+        "tests/LocalUnwinderTest.cpp",
+    ],
     required: [
         "libunwindstack_local",
     ],
 }
 
+// Skip LocalUnwinderTest until atest understands required properly.
+cc_test {
+    name: "libunwindstack_unit_test",
+    defaults: ["libunwindstack_testlib_flags"],
+    isolated: true,
+}
+
 //-------------------------------------------------------------------------
 // Tools
 //-------------------------------------------------------------------------
diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md
new file mode 100644
index 0000000..234f639
--- /dev/null
+++ b/libunwindstack/AndroidVersions.md
@@ -0,0 +1,116 @@
+# Unwinder Support Per Android Release
+This document describes the changes in the way the libunwindstack
+unwinder works on different Android versions. It does not describe
+every change in the code made between different versions, but is
+meant to allow an app developer to know what might be supported
+on different versions. It also describes the different way an unwind
+will display on different versions of Android.
+
+## Android P
+libunwindstack was first introduced in Android P.
+
+* Supports up to and including Dwarf 4 unwinding information.
+  See http://dwarfstd.org/ for Dwarf standards.
+* Supports Arm exidx unwinding.
+* Supports the gdb JIT unwinding interface, which is how ART creates unwinding
+  information for the JIT'd Java frames.
+* Supports special frames added to represent an ART Java interpreter frame.
+  ART has marked the dex pc using cfi information that the unwinder
+  understands and handles by adding a new frame in the stacktrace.
+
+## Note
+By default, lld creates two separate maps of the elf in memory, one read-only
+and one read/executable. The libunwindstack on P and the unwinder on older
+versions of Android will not unwind properly in this case. For apps that
+target Android P or older, make sure that `-Wl,--no-rosegment` is
+included in linker arguments when using lld.
+
+## Android Q
+* Fix bug (b/109824792) that handled load bias data incorrectly when
+  FDEs use pc relative addressing in the eh\_frame\_hdr.
+  Unfortunately, this wasn't fixed correctly in Q since it assumes
+  that the bias is coming from the program header for the executable
+  load. The real fix was to use the bias from the actual section data and
+  is not completely fixed until Android R. For apps targeting Android Q,
+  if it is being compiled with the llvm linker lld, it might be necessary
+  to add the linker option `-Wl,-zseparate-code` to avoid creating an elf
+  created this way.
+* Change the way the exidx section offset is found (b/110704153). Before
+  the p\_vaddr value from the program header minus the load bias was used
+  to find the start of the exidx data. Changed to use the p\_offset since
+  it doesn't require any load bias manipulations.
+* Fix bug handling of dwarf sections without any header (b/110235461).
+  Previously, the code assumed that FDEs are non-overlapping, and the FDEs
+  are always in sorted order from low pc to high pc. Thus the code would
+  read the entire set of CIEs/FDEs and then do a binary search to find
+  the appropriate FDE for a given pc. Now the code does a sequential read
+  and stops when it finds the FDE for a pc. It also understands the
+  overlapping FDEs, so find the first FDE that matches a pc. In practice,
+  elf files with this format only ever occurs if the file was generated
+  without an eh\_frame/eh\_frame\_hdr section and only a debug\_frame. The
+  other way this has been observed is when running simpleperf to unwind since
+  sometimes there is not enough information in the eh\_frame for all points
+  in the executable. On Android P, this would result in some incorrect
+  unwinds coming from simpleperf. Nearly all crashes from Android P should
+  be correct since the eh\_frame information was enough to do the unwind
+  properly.
+* Be permissive of badly formed elf files. Previously, any detected error
+  would result in unwinds stopping even if there is enough valid information
+  to do an unwind.
+  * The code now allows program header/section header offsets to point
+    to unreadable memory. As long as the code can find the unwind tables,
+    that is good enough.
+  * The code allows program headers/section headers to be missing.
+  * Allow a symbol table section header to point to invalid symbol table
+    values.
+* Support for the linker read-only segment option (b/109657296).
+  This is a feature of lld whereby there are two sections that
+  contain elf data. The first is read-only and contains the elf header data,
+  and the second is read-execute or execute only that
+  contains the executable code from the elf. Before this, the unwinder
+  always assumed that there was only a single read-execute section that
+  contained the elf header data and the executable code.
+* Build ID information for elf objects added. This will display the
+  NT\_GNU\_BUILD\_ID note found in elf files. This information can be used
+  to identify the exact version of a shared library to help get symbol
+  information when looking at a crash.
+* Add support for displaying the soname from an apk frame. Previously,
+  a frame map name would be only the apk, but now if the shared library
+  in the apk has set a soname, the map name will be `app.apk!libexample.so`
+  instead of only `app.apk`.
+* Minimal support for Dwarf 5. This merely treats a Dwarf 5 version
+  elf file as Dwarf 4. It does not support the new dwarf ops in Dwarf 5.
+  Since the new ops are not likely to be used very often, this allows
+  continuing to unwind even when encountering Dwarf 5 elf files.
+* Fix bug in pc handling of signal frames (b/130302288). In the previous
+  version, the pc would be wrong in the signal frame. The rest of the
+  unwind was correct, only the frame in the signal handler was incorrect
+  in Android P.
+* Detect when an elf file is not readable so that a message can be
+  displayed indicating that. This can happen when an app puts the shared
+  libraries in non-standard locations that are not readable due to
+  security restrictions (selinux rules).
+
+## Android R
+* Display the offsets for Java interpreter frames. If this frame came
+  from a non-zero offset map, no offset is printed. Previously, the
+  line would look like:
+
+    #17 pc 00500d7a  GoogleCamera.apk (com.google.camera.AndroidPriorityThread.run+10)
+
+  to:
+
+    #17 pc 00500d7a  GoogleCamera.apk (offset 0x11d0000) (com.google.camera.AndroidPriorityThread.run+10)
+* Fix bug where the load bias was set from the first PT\_LOAD program
+  header that has a zero p\_offset value. Now it is set from the first
+  executable PT\_LOAD program header. This has only ever been a problem
+  for host executables compiled for the x86\_64 architecture.
+* Switched to the libc++ demangler for function names. Previously, the
+  demangler used was not complete, so some less common demangled function
+  names would not be properly demangled or the function name would not be
+  demangled at all.
+* Fix bug in load bias handling. If the unwind information in the eh\_frame
+  or eh\_frame\_hdr does not have the same bias as the executable section,
+  and uses pc relative FDEs, the unwind will be incorrect. This tends
+  to truncate unwinds since the unwinder could not find the correct unwind
+  information for a given pc.
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index eaf867f..dff7a8b 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -22,6 +22,9 @@
 
 #include <memory>
 
+#define LOG_TAG "unwind"
+#include <log/log.h>
+
 #include <android-base/unique_fd.h>
 #include <art_api/dex_file_support.h>
 
@@ -32,6 +35,19 @@
 
 namespace unwindstack {
 
+static bool CheckDexSupport() {
+  if (std::string err_msg; !art_api::dex::TryLoadLibdexfileExternal(&err_msg)) {
+    ALOGW("Failed to initialize DEX file support: %s", err_msg.c_str());
+    return false;
+  }
+  return true;
+}
+
+static bool HasDexSupport() {
+  static bool has_dex_support = CheckDexSupport();
+  return has_dex_support;
+}
+
 std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
                                          MapInfo* info) {
   if (!info->name.empty()) {
@@ -57,6 +73,10 @@
 
 std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offset_in_file,
                                                          const std::string& file) {
+  if (UNLIKELY(!HasDexSupport())) {
+    return nullptr;
+  }
+
   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
   if (fd == -1) {
     return nullptr;
@@ -75,6 +95,10 @@
 std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
                                                              Memory* memory,
                                                              const std::string& name) {
+  if (UNLIKELY(!HasDexSupport())) {
+    return nullptr;
+  }
+
   std::vector<uint8_t> backing_memory;
 
   for (size_t size = 0;;) {
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 63a77e5..2057fad 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -27,10 +27,21 @@
 #include <unwindstack/Maps.h>
 #include <unwindstack/Memory.h>
 
+#if defined(DEXFILE_SUPPORT)
 #include "DexFile.h"
+#endif
 
 namespace unwindstack {
 
+#if !defined(DEXFILE_SUPPORT)
+// Empty class definition.
+class DexFile {
+ public:
+  DexFile() = default;
+  virtual ~DexFile() = default;
+};
+#endif
+
 struct DEXFileEntry32 {
   uint32_t next;
   uint32_t prev;
@@ -128,6 +139,7 @@
   FindAndReadVariable(maps, "__dex_debug_descriptor");
 }
 
+#if defined(DEXFILE_SUPPORT)
 DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
   // Lock while processing the data.
   DexFile* dex_file;
@@ -141,6 +153,11 @@
   }
   return dex_file;
 }
+#else
+DexFile* DexFiles::GetDexFile(uint64_t, MapInfo*) {
+  return nullptr;
+}
+#endif
 
 bool DexFiles::GetAddr(size_t index, uint64_t* addr) {
   if (index < addrs_.size()) {
@@ -154,6 +171,7 @@
   return false;
 }
 
+#if defined(DEXFILE_SUPPORT)
 void DexFiles::GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc,
                                     std::string* method_name, uint64_t* method_offset) {
   std::lock_guard<std::mutex> guard(lock_);
@@ -175,5 +193,8 @@
     }
   }
 }
+#else
+void DexFiles::GetMethodInformation(Maps*, MapInfo*, uint64_t, std::string*, uint64_t*) {}
+#endif
 
 }  // namespace unwindstack
diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h
index 388ab0a..635cefd 100644
--- a/libunwindstack/DwarfDebugFrame.h
+++ b/libunwindstack/DwarfDebugFrame.h
@@ -26,9 +26,9 @@
 namespace unwindstack {
 
 template <typename AddressType>
-class DwarfDebugFrame : public DwarfSectionImplNoHdr<AddressType> {
+class DwarfDebugFrame : public DwarfSectionImpl<AddressType> {
  public:
-  DwarfDebugFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {
+  DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {
     this->cie32_value_ = static_cast<uint32_t>(-1);
     this->cie64_value_ = static_cast<uint64_t>(-1);
   }
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
index df441fb..7a41e45 100644
--- a/libunwindstack/DwarfEhFrame.h
+++ b/libunwindstack/DwarfEhFrame.h
@@ -25,9 +25,9 @@
 namespace unwindstack {
 
 template <typename AddressType>
-class DwarfEhFrame : public DwarfSectionImplNoHdr<AddressType> {
+class DwarfEhFrame : public DwarfSectionImpl<AddressType> {
  public:
-  DwarfEhFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {}
+  DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
   virtual ~DwarfEhFrame() = default;
 
   uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index 802beca..1358e51 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -32,14 +32,19 @@
 }
 
 template <typename AddressType>
-bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
-  load_bias_ = load_bias;
+bool DwarfEhFrameWithHdr<AddressType>::EhFrameInit(uint64_t offset, uint64_t size,
+                                                   int64_t section_bias) {
+  return DwarfSectionImpl<AddressType>::Init(offset, size, section_bias);
+}
 
+template <typename AddressType>
+bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t, int64_t section_bias) {
   memory_.clear_func_offset();
   memory_.clear_text_offset();
   memory_.set_data_offset(offset);
   memory_.set_cur_offset(offset);
-  pc_offset_ = offset;
+
+  hdr_section_bias_ = section_bias;
 
   // Read the first four bytes all at once.
   uint8_t data[4];
@@ -56,7 +61,7 @@
     return false;
   }
 
-  ptr_encoding_ = data[1];
+  uint8_t ptr_encoding = data[1];
   uint8_t fde_count_encoding = data[2];
   table_encoding_ = data[3];
   table_entry_size_ = memory_.template GetEncodedSize<AddressType>(table_encoding_);
@@ -70,7 +75,8 @@
   }
 
   memory_.set_pc_offset(memory_.cur_offset());
-  if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) {
+  uint64_t ptr_offset;
+  if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding, &ptr_offset)) {
     last_error_.code = DWARF_ERROR_MEMORY_INVALID;
     last_error_.address = memory_.cur_offset();
     return false;
@@ -88,10 +94,8 @@
     return false;
   }
 
-  entries_offset_ = memory_.cur_offset();
-  entries_end_ = offset + size;
-  entries_data_offset_ = offset;
-  cur_entries_offset_ = entries_offset_;
+  hdr_entries_offset_ = memory_.cur_offset();
+  hdr_entries_data_offset_ = offset;
 
   return true;
 }
@@ -107,6 +111,16 @@
     return nullptr;
   }
 
+  // There is a possibility that this entry points to a zero length FDE
+  // due to a bug. If this happens, try and find the non-zero length FDE
+  // from eh_frame directly. See b/142483624.
+  if (fde->pc_start == fde->pc_end) {
+    fde = DwarfSectionImpl<AddressType>::GetFdeFromPc(pc);
+    if (fde == nullptr) {
+      return nullptr;
+    }
+  }
+
   // Guaranteed pc >= pc_start, need to check pc in the fde range.
   if (pc < fde->pc_end) {
     return fde;
@@ -124,8 +138,8 @@
   }
   FdeInfo* info = &fde_info_[index];
 
-  memory_.set_data_offset(entries_data_offset_);
-  memory_.set_cur_offset(entries_offset_ + 2 * index * table_entry_size_);
+  memory_.set_data_offset(hdr_entries_data_offset_);
+  memory_.set_cur_offset(hdr_entries_offset_ + 2 * index * table_entry_size_);
   memory_.set_pc_offset(0);
   uint64_t value;
   if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
@@ -138,7 +152,7 @@
 
   // Relative encodings require adding in the load bias.
   if (IsEncodingRelative(table_encoding_)) {
-    value += load_bias_;
+    value += hdr_section_bias_;
   }
   info->pc = value;
   return info;
@@ -190,6 +204,16 @@
     if (fde == nullptr) {
       break;
     }
+
+    // There is a possibility that this entry points to a zero length FDE
+    // due to a bug. If this happens, try and find the non-zero length FDE
+    // from eh_frame directly. See b/142483624.
+    if (fde->pc_start == fde->pc_end) {
+      const DwarfFde* fde_real = DwarfSectionImpl<AddressType>::GetFdeFromPc(fde->pc_start);
+      if (fde_real != nullptr) {
+        fde = fde_real;
+      }
+    }
     fdes->push_back(fde);
   }
 }
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
index 0e5eef7..f7c010c 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -34,11 +34,7 @@
   // Add these so that the protected members of DwarfSectionImpl
   // can be accessed without needing a this->.
   using DwarfSectionImpl<AddressType>::memory_;
-  using DwarfSectionImpl<AddressType>::pc_offset_;
-  using DwarfSectionImpl<AddressType>::entries_offset_;
-  using DwarfSectionImpl<AddressType>::entries_end_;
   using DwarfSectionImpl<AddressType>::last_error_;
-  using DwarfSectionImpl<AddressType>::load_bias_;
 
   struct FdeInfo {
     AddressType pc;
@@ -49,19 +45,20 @@
   virtual ~DwarfEhFrameWithHdr() = default;
 
   uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
-    return this->memory_.cur_offset() - pointer - 4;
+    return memory_.cur_offset() - pointer - 4;
   }
 
   uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
-    return this->memory_.cur_offset() - pointer - 8;
+    return memory_.cur_offset() - pointer - 8;
   }
 
   uint64_t AdjustPcFromFde(uint64_t pc) override {
     // The eh_frame uses relative pcs.
-    return pc + this->memory_.cur_offset() - 4;
+    return pc + memory_.cur_offset() - 4;
   }
 
-  bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
+  bool EhFrameInit(uint64_t offset, uint64_t size, int64_t section_bias);
+  bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
 
   const DwarfFde* GetFdeFromPc(uint64_t pc) override;
 
@@ -72,17 +69,15 @@
   void GetFdes(std::vector<const DwarfFde*>* fdes) override;
 
  protected:
-  uint8_t version_;
-  uint8_t ptr_encoding_;
-  uint8_t table_encoding_;
-  size_t table_entry_size_;
+  uint8_t version_ = 0;
+  uint8_t table_encoding_ = 0;
+  size_t table_entry_size_ = 0;
 
-  uint64_t ptr_offset_;
+  uint64_t hdr_entries_offset_ = 0;
+  uint64_t hdr_entries_data_offset_ = 0;
+  uint64_t hdr_section_bias_ = 0;
 
-  uint64_t entries_data_offset_;
-  uint64_t cur_entries_offset_ = 0;
-
-  uint64_t fde_count_;
+  uint64_t fde_count_ = 0;
   std::unordered_map<uint64_t, FdeInfo> fde_info_;
 };
 
diff --git a/libunwindstack/DwarfMemory.cpp b/libunwindstack/DwarfMemory.cpp
index b505900..2e388c6 100644
--- a/libunwindstack/DwarfMemory.cpp
+++ b/libunwindstack/DwarfMemory.cpp
@@ -111,7 +111,7 @@
       // Nothing to do.
       break;
     case DW_EH_PE_pcrel:
-      if (pc_offset_ == static_cast<uint64_t>(-1)) {
+      if (pc_offset_ == INT64_MAX) {
         // Unsupported encoding.
         return false;
       }
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 849a31a..e6263f8 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -69,6 +69,7 @@
     return &cie_entry->second;
   }
   DwarfCie* cie = &cie_entries_[offset];
+  memory_.set_data_offset(entries_offset_);
   memory_.set_cur_offset(offset);
   if (!FillInCieHeader(cie) || !FillInCie(cie)) {
     // Erase the cached entry.
@@ -251,6 +252,7 @@
     return &fde_entry->second;
   }
   DwarfFde* fde = &fde_entries_[offset];
+  memory_.set_data_offset(entries_offset_);
   memory_.set_cur_offset(offset);
   if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
     fde_entries_.erase(offset);
@@ -333,7 +335,7 @@
   memory_.set_cur_offset(cur_offset);
 
   // The load bias only applies to the start.
-  memory_.set_pc_offset(load_bias_);
+  memory_.set_pc_offset(section_bias_);
   bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start);
   fde->pc_start = AdjustPcFromFde(fde->pc_start);
 
@@ -591,8 +593,8 @@
 }
 
 template <typename AddressType>
-bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
-  load_bias_ = load_bias;
+bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, int64_t section_bias) {
+  section_bias_ = section_bias;
   entries_offset_ = offset;
   next_entries_offset_ = offset;
   entries_end_ = offset + size;
@@ -600,7 +602,6 @@
   memory_.clear_func_offset();
   memory_.clear_text_offset();
   memory_.set_cur_offset(offset);
-  memory_.set_data_offset(offset);
   pc_offset_ = offset;
 
   return true;
@@ -616,7 +617,7 @@
 // and an fde has a start pc of 0x100 and end pc of 0x500, two new entries
 // will be added: 0x200, 0x100 and 0x500, 0x400.
 template <typename AddressType>
-void DwarfSectionImplNoHdr<AddressType>::InsertFde(const DwarfFde* fde) {
+void DwarfSectionImpl<AddressType>::InsertFde(const DwarfFde* fde) {
   uint64_t start = fde->pc_start;
   uint64_t end = fde->pc_end;
   auto it = fdes_.upper_bound(start);
@@ -653,9 +654,10 @@
 }
 
 template <typename AddressType>
-bool DwarfSectionImplNoHdr<AddressType>::GetNextCieOrFde(DwarfFde** fde_entry) {
+bool DwarfSectionImpl<AddressType>::GetNextCieOrFde(const DwarfFde** fde_entry) {
   uint64_t start_offset = next_entries_offset_;
 
+  memory_.set_data_offset(entries_offset_);
   memory_.set_cur_offset(next_entries_offset_);
   uint32_t value32;
   if (!memory_.ReadBytes(&value32, sizeof(value32))) {
@@ -688,7 +690,7 @@
       entry_is_cie = true;
       cie_fde_encoding = DW_EH_PE_sdata8;
     } else {
-      cie_offset = this->GetCieOffsetFromFde64(value64);
+      cie_offset = GetCieOffsetFromFde64(value64);
     }
   } else {
     next_entries_offset_ = memory_.cur_offset() + value32;
@@ -704,37 +706,45 @@
       entry_is_cie = true;
       cie_fde_encoding = DW_EH_PE_sdata4;
     } else {
-      cie_offset = this->GetCieOffsetFromFde32(value32);
+      cie_offset = GetCieOffsetFromFde32(value32);
     }
   }
 
   if (entry_is_cie) {
-    DwarfCie* cie = &cie_entries_[start_offset];
-    cie->lsda_encoding = DW_EH_PE_omit;
-    cie->cfa_instructions_end = next_entries_offset_;
-    cie->fde_address_encoding = cie_fde_encoding;
+    auto entry = cie_entries_.find(start_offset);
+    if (entry == cie_entries_.end()) {
+      DwarfCie* cie = &cie_entries_[start_offset];
+      cie->lsda_encoding = DW_EH_PE_omit;
+      cie->cfa_instructions_end = next_entries_offset_;
+      cie->fde_address_encoding = cie_fde_encoding;
 
-    if (!this->FillInCie(cie)) {
-      cie_entries_.erase(start_offset);
-      return false;
+      if (!FillInCie(cie)) {
+        cie_entries_.erase(start_offset);
+        return false;
+      }
     }
     *fde_entry = nullptr;
   } else {
-    DwarfFde* fde = &fde_entries_[start_offset];
-    fde->cfa_instructions_end = next_entries_offset_;
-    fde->cie_offset = cie_offset;
+    auto entry = fde_entries_.find(start_offset);
+    if (entry != fde_entries_.end()) {
+      *fde_entry = &entry->second;
+    } else {
+      DwarfFde* fde = &fde_entries_[start_offset];
+      fde->cfa_instructions_end = next_entries_offset_;
+      fde->cie_offset = cie_offset;
 
-    if (!this->FillInFde(fde)) {
-      fde_entries_.erase(start_offset);
-      return false;
+      if (!FillInFde(fde)) {
+        fde_entries_.erase(start_offset);
+        return false;
+      }
+      *fde_entry = fde;
     }
-    *fde_entry = fde;
   }
   return true;
 }
 
 template <typename AddressType>
-void DwarfSectionImplNoHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
+void DwarfSectionImpl<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
   // Loop through the already cached entries.
   uint64_t entry_offset = entries_offset_;
   while (entry_offset < next_entries_offset_) {
@@ -753,7 +763,7 @@
   }
 
   while (next_entries_offset_ < entries_end_) {
-    DwarfFde* fde;
+    const DwarfFde* fde;
     if (!GetNextCieOrFde(&fde)) {
       break;
     }
@@ -770,7 +780,7 @@
 }
 
 template <typename AddressType>
-const DwarfFde* DwarfSectionImplNoHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
+const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromPc(uint64_t pc) {
   // Search in the list of fdes we already have.
   auto it = fdes_.upper_bound(pc);
   if (it != fdes_.end()) {
@@ -783,7 +793,7 @@
   // to do a linear search of the fdes by pc. As fdes are read, a cached
   // search map is created.
   while (next_entries_offset_ < entries_end_) {
-    DwarfFde* fde;
+    const DwarfFde* fde;
     if (!GetNextCieOrFde(&fde)) {
       return nullptr;
     }
@@ -806,10 +816,6 @@
 template class DwarfSectionImpl<uint32_t>;
 template class DwarfSectionImpl<uint64_t>;
 
-// Explicitly instantiate DwarfSectionImplNoHdr
-template class DwarfSectionImplNoHdr<uint32_t>;
-template class DwarfSectionImplNoHdr<uint64_t>;
-
 // Explicitly instantiate DwarfDebugFrame
 template class DwarfDebugFrame<uint32_t>;
 template class DwarfDebugFrame<uint64_t>;
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 3454913..f01b092 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -53,7 +53,7 @@
 
   valid_ = interface_->Init(&load_bias_);
   if (valid_) {
-    interface_->InitHeaders(load_bias_);
+    interface_->InitHeaders();
     InitGnuDebugdata();
   } else {
     interface_.reset(nullptr);
@@ -77,9 +77,9 @@
 
   // Ignore the load_bias from the compressed section, the correct load bias
   // is in the uncompressed data.
-  uint64_t load_bias;
+  int64_t load_bias;
   if (gnu->Init(&load_bias)) {
-    gnu->InitHeaders(load_bias);
+    gnu->InitHeaders();
     interface_->SetGnuDebugdataInterface(gnu);
   } else {
     // Free all of the memory associated with the gnu_debugdata section.
@@ -112,35 +112,33 @@
                      gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
 }
 
-bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
+bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) {
   if (!valid_) {
     return false;
   }
 
-  if (!interface_->GetGlobalVariable(name, memory_address) &&
+  uint64_t vaddr;
+  if (!interface_->GetGlobalVariable(name, &vaddr) &&
       (gnu_debugdata_interface_ == nullptr ||
-       !gnu_debugdata_interface_->GetGlobalVariable(name, memory_address))) {
+       !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) {
     return false;
   }
 
-  // Adjust by the load bias.
-  if (*memory_address < load_bias_) {
-    return false;
+  // Check the .data section.
+  uint64_t vaddr_start = interface_->data_vaddr_start();
+  if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) {
+    *memory_offset = vaddr - vaddr_start + interface_->data_offset();
+    return true;
   }
 
-  *memory_address -= load_bias_;
-
-  // If this winds up in the dynamic section, then we might need to adjust
-  // the address.
-  uint64_t dynamic_end = interface_->dynamic_vaddr() + interface_->dynamic_size();
-  if (*memory_address >= interface_->dynamic_vaddr() && *memory_address < dynamic_end) {
-    if (interface_->dynamic_vaddr() > interface_->dynamic_offset()) {
-      *memory_address -= interface_->dynamic_vaddr() - interface_->dynamic_offset();
-    } else {
-      *memory_address += interface_->dynamic_offset() - interface_->dynamic_vaddr();
-    }
+  // Check the .dynamic section.
+  vaddr_start = interface_->dynamic_vaddr_start();
+  if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) {
+    *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset();
+    return true;
   }
-  return true;
+
+  return false;
 }
 
 std::string Elf::GetBuildID() {
@@ -175,7 +173,12 @@
   if (!valid_) {
     return false;
   }
-  return regs->StepIfSignalHandler(rel_pc, this, process_memory);
+
+  // Convert the rel_pc to an elf_offset.
+  if (rel_pc < static_cast<uint64_t>(load_bias_)) {
+    return false;
+  }
+  return regs->StepIfSignalHandler(rel_pc - load_bias_, this, process_memory);
 }
 
 // The relative pc is always relative to the start of the map from which it comes.
@@ -229,7 +232,7 @@
 }
 
 bool Elf::IsValidPc(uint64_t pc) {
-  if (!valid_ || pc < load_bias_) {
+  if (!valid_ || (load_bias_ > 0 && pc < static_cast<uint64_t>(load_bias_))) {
     return false;
   }
 
@@ -299,7 +302,7 @@
   return interface.release();
 }
 
-uint64_t Elf::GetLoadBias(Memory* memory) {
+int64_t Elf::GetLoadBias(Memory* memory) {
   if (!IsValidElf(memory)) {
     return 0;
   }
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index dee8eb3..341275d 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -29,12 +29,12 @@
 #include <unwindstack/DwarfSection.h>
 #include <unwindstack/ElfInterface.h>
 #include <unwindstack/Log.h>
-#include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
 
 #include "DwarfDebugFrame.h"
 #include "DwarfEhFrame.h"
 #include "DwarfEhFrameWithHdr.h"
+#include "MemoryBuffer.h"
 #include "Symbols.h"
 
 namespace unwindstack {
@@ -78,10 +78,31 @@
   CrcGenerateTable();
   Crc64GenerateTable();
 
-  std::vector<uint8_t> src(gnu_debugdata_size_);
-  if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
-    gnu_debugdata_offset_ = 0;
-    gnu_debugdata_size_ = static_cast<uint64_t>(-1);
+  // Verify the request is not larger than the max size_t value.
+  if (gnu_debugdata_size_ > SIZE_MAX) {
+    return nullptr;
+  }
+  size_t initial_buffer_size;
+  if (__builtin_mul_overflow(5, gnu_debugdata_size_, &initial_buffer_size)) {
+    return nullptr;
+  }
+
+  size_t buffer_increment;
+  if (__builtin_mul_overflow(2, gnu_debugdata_size_, &buffer_increment)) {
+    return nullptr;
+  }
+
+  std::unique_ptr<uint8_t[]> src(new (std::nothrow) uint8_t[gnu_debugdata_size_]);
+  if (src.get() == nullptr) {
+    return nullptr;
+  }
+
+  std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
+  if (!dst->Resize(initial_buffer_size)) {
+    return nullptr;
+  }
+
+  if (!memory_->ReadFully(gnu_debugdata_offset_, src.get(), gnu_debugdata_size_)) {
     return nullptr;
   }
 
@@ -89,21 +110,23 @@
   CXzUnpacker state;
   alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
   alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
-
   XzUnpacker_Construct(&state, &alloc);
 
-  std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
   int return_val;
   size_t src_offset = 0;
   size_t dst_offset = 0;
   ECoderStatus status;
-  dst->Resize(5 * gnu_debugdata_size_);
   do {
-    size_t src_remaining = src.size() - src_offset;
+    size_t src_remaining = gnu_debugdata_size_ - src_offset;
     size_t dst_remaining = dst->Size() - dst_offset;
-    if (dst_remaining < 2 * gnu_debugdata_size_) {
-      dst->Resize(dst->Size() + 2 * gnu_debugdata_size_);
-      dst_remaining += 2 * gnu_debugdata_size_;
+    if (dst_remaining < buffer_increment) {
+      size_t new_size;
+      if (__builtin_add_overflow(dst->Size(), buffer_increment, &new_size) ||
+          !dst->Resize(new_size)) {
+        XzUnpacker_Free(&state);
+        return nullptr;
+      }
+      dst_remaining += buffer_increment;
     }
     return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
                                  &src_remaining, true, CODER_FINISH_ANY, &status);
@@ -112,22 +135,24 @@
   } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
   XzUnpacker_Free(&state);
   if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
-    gnu_debugdata_offset_ = 0;
-    gnu_debugdata_size_ = static_cast<uint64_t>(-1);
     return nullptr;
   }
 
   // Shrink back down to the exact size.
-  dst->Resize(dst_offset);
+  if (!dst->Resize(dst_offset)) {
+    return nullptr;
+  }
 
   return dst.release();
 }
 
 template <typename AddressType>
-void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
+void ElfInterface::InitHeadersWithTemplate() {
   if (eh_frame_hdr_offset_ != 0) {
-    eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
-    if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, load_bias)) {
+    DwarfEhFrameWithHdr<AddressType>* eh_frame_hdr = new DwarfEhFrameWithHdr<AddressType>(memory_);
+    eh_frame_.reset(eh_frame_hdr);
+    if (!eh_frame_hdr->EhFrameInit(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_) ||
+        !eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) {
       eh_frame_.reset(nullptr);
     }
   }
@@ -136,21 +161,23 @@
     // If there is an eh_frame section without an eh_frame_hdr section,
     // or using the frame hdr object failed to init.
     eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
-    if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, load_bias)) {
+    if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_)) {
       eh_frame_.reset(nullptr);
     }
   }
 
   if (eh_frame_.get() == nullptr) {
     eh_frame_hdr_offset_ = 0;
+    eh_frame_hdr_section_bias_ = 0;
     eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
     eh_frame_offset_ = 0;
+    eh_frame_section_bias_ = 0;
     eh_frame_size_ = static_cast<uint64_t>(-1);
   }
 
   if (debug_frame_offset_ != 0) {
     debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
-    if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, load_bias)) {
+    if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, debug_frame_section_bias_)) {
       debug_frame_.reset(nullptr);
       debug_frame_offset_ = 0;
       debug_frame_size_ = static_cast<uint64_t>(-1);
@@ -159,7 +186,7 @@
 }
 
 template <typename EhdrType, typename PhdrType, typename ShdrType>
-bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
+bool ElfInterface::ReadAllHeaders(int64_t* load_bias) {
   EhdrType ehdr;
   if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
     last_error_.code = ERROR_MEMORY_INVALID;
@@ -175,7 +202,7 @@
 }
 
 template <typename EhdrType, typename PhdrType>
-uint64_t ElfInterface::GetLoadBias(Memory* memory) {
+int64_t ElfInterface::GetLoadBias(Memory* memory) {
   EhdrType ehdr;
   if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
     return false;
@@ -187,16 +214,19 @@
     if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) {
       return 0;
     }
-    if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
-      return phdr.p_vaddr;
+
+    // Find the first executable load when looking for the load bias.
+    if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) {
+      return static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
     }
   }
   return 0;
 }
 
 template <typename EhdrType, typename PhdrType>
-void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
+void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) {
   uint64_t offset = ehdr.e_phoff;
+  bool first_exec_load_header = true;
   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
     PhdrType phdr;
     if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
@@ -212,22 +242,29 @@
 
       pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
                                           static_cast<size_t>(phdr.p_memsz)};
-      if (phdr.p_offset == 0) {
-        *load_bias = phdr.p_vaddr;
+      // Only set the load bias from the first executable load header.
+      if (first_exec_load_header) {
+        *load_bias = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
       }
+      first_exec_load_header = false;
       break;
     }
 
     case PT_GNU_EH_FRAME:
       // This is really the pointer to the .eh_frame_hdr section.
       eh_frame_hdr_offset_ = phdr.p_offset;
+      eh_frame_hdr_section_bias_ = static_cast<uint64_t>(phdr.p_vaddr) - phdr.p_offset;
       eh_frame_hdr_size_ = phdr.p_memsz;
       break;
 
     case PT_DYNAMIC:
       dynamic_offset_ = phdr.p_offset;
-      dynamic_vaddr_ = phdr.p_vaddr;
-      dynamic_size_ = phdr.p_memsz;
+      dynamic_vaddr_start_ = phdr.p_vaddr;
+      if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) {
+        dynamic_offset_ = 0;
+        dynamic_vaddr_start_ = 0;
+        dynamic_vaddr_end_ = 0;
+      }
       break;
 
     default:
@@ -335,24 +372,29 @@
       if (shdr.sh_name < sec_size) {
         std::string name;
         if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
-          uint64_t* offset_ptr = nullptr;
-          uint64_t* size_ptr = nullptr;
           if (name == ".debug_frame") {
-            offset_ptr = &debug_frame_offset_;
-            size_ptr = &debug_frame_size_;
+            debug_frame_offset_ = shdr.sh_offset;
+            debug_frame_size_ = shdr.sh_size;
+            debug_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
           } else if (name == ".gnu_debugdata") {
-            offset_ptr = &gnu_debugdata_offset_;
-            size_ptr = &gnu_debugdata_size_;
+            gnu_debugdata_offset_ = shdr.sh_offset;
+            gnu_debugdata_size_ = shdr.sh_size;
           } else if (name == ".eh_frame") {
-            offset_ptr = &eh_frame_offset_;
-            size_ptr = &eh_frame_size_;
+            eh_frame_offset_ = shdr.sh_offset;
+            eh_frame_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
+            eh_frame_size_ = shdr.sh_size;
           } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
-            offset_ptr = &eh_frame_hdr_offset_;
-            size_ptr = &eh_frame_hdr_size_;
-          }
-          if (offset_ptr != nullptr) {
-            *offset_ptr = shdr.sh_offset;
-            *size_ptr = shdr.sh_size;
+            eh_frame_hdr_offset_ = shdr.sh_offset;
+            eh_frame_hdr_section_bias_ = static_cast<uint64_t>(shdr.sh_addr) - shdr.sh_offset;
+            eh_frame_hdr_size_ = shdr.sh_size;
+          } else if (name == ".data") {
+            data_offset_ = shdr.sh_offset;
+            data_vaddr_start_ = shdr.sh_addr;
+            if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) {
+              data_offset_ = 0;
+              data_vaddr_start_ = 0;
+              data_vaddr_end_ = 0;
+            }
           }
         }
       }
@@ -391,7 +433,7 @@
   // Find the soname location from the dynamic headers section.
   DynType dyn;
   uint64_t offset = dynamic_offset_;
-  uint64_t max_offset = offset + dynamic_size_;
+  uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_;
   for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
     if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
       last_error_.code = ERROR_MEMORY_INVALID;
@@ -634,16 +676,14 @@
 }
 
 // Instantiate all of the needed template functions.
-template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
-template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
+template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
+template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
 
-template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
-template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
+template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(int64_t*);
+template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(int64_t*);
 
-template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&,
-                                                                       uint64_t*);
-template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&,
-                                                                       uint64_t*);
+template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&, int64_t*);
+template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&, int64_t*);
 
 template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
 template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
@@ -665,8 +705,8 @@
 template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
 template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
 
-template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
-template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
+template int64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
+template int64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
 
 template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
     Memory*);
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 3dd5d54..76f2dc8 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -26,7 +26,7 @@
 
 namespace unwindstack {
 
-bool ElfInterfaceArm::Init(uint64_t* load_bias) {
+bool ElfInterfaceArm::Init(int64_t* load_bias) {
   if (!ElfInterface32::Init(load_bias)) {
     return false;
   }
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
index 4c3a0c3..1d71cac 100644
--- a/libunwindstack/ElfInterfaceArm.h
+++ b/libunwindstack/ElfInterfaceArm.h
@@ -64,7 +64,7 @@
   iterator begin() { return iterator(this, 0); }
   iterator end() { return iterator(this, total_entries_); }
 
-  bool Init(uint64_t* load_bias) override;
+  bool Init(int64_t* section_bias) override;
 
   bool GetPrel31Addr(uint32_t offset, uint32_t* addr);
 
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
index a20be00..ec977e1 100644
--- a/libunwindstack/Global.cpp
+++ b/libunwindstack/Global.cpp
@@ -39,28 +39,22 @@
   }
 }
 
-uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) {
-  if (!search_libs_.empty()) {
-    bool found = false;
-    const char* lib = basename(info->name.c_str());
-    for (const std::string& name : search_libs_) {
-      if (name == lib) {
-        found = true;
-        break;
-      }
-    }
-    if (!found) {
-      return 0;
-    }
+bool Global::Searchable(const std::string& name) {
+  if (search_libs_.empty()) {
+    return true;
   }
 
-  Elf* elf = info->GetElf(memory_, arch());
-  uint64_t ptr;
-  // Find first non-empty list (libraries might be loaded multiple times).
-  if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
-    return ptr + info->start;
+  if (name.empty()) {
+    return false;
   }
-  return 0;
+
+  const char* base_name = basename(name.c_str());
+  for (const std::string& lib : search_libs_) {
+    if (base_name == lib) {
+      return true;
+    }
+  }
+  return false;
 }
 
 void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
@@ -78,24 +72,27 @@
   //   f2000-f3000 2000 rw- /system/lib/libc.so
   MapInfo* map_start = nullptr;
   for (const auto& info : *maps) {
-    if (map_start != nullptr) {
-      if (map_start->name == info->name) {
-        if (info->offset != 0 &&
-            (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
-          uint64_t ptr = GetVariableOffset(map_start, variable);
-          if (ptr != 0 && ReadVariableData(ptr)) {
-            break;
-          } else {
-            // Failed to find the global variable, do not bother trying again.
-            map_start = nullptr;
+    if (map_start != nullptr && map_start->name == info->name) {
+      if (info->offset != 0 &&
+          (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
+        Elf* elf = map_start->GetElf(memory_, arch());
+        uint64_t ptr;
+        if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) {
+          uint64_t offset_end = info->offset + info->end - info->start;
+          if (ptr >= info->offset && ptr < offset_end) {
+            ptr = info->start + ptr - info->offset;
+            if (ReadVariableData(ptr)) {
+              break;
+            }
           }
         }
-      } else {
         map_start = nullptr;
       }
+    } else {
+      map_start = nullptr;
     }
     if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
-        !info->name.empty()) {
+        Searchable(info->name)) {
       map_start = info.get();
     }
   }
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
index 20bc4b9..8a85607 100644
--- a/libunwindstack/JitDebug.cpp
+++ b/libunwindstack/JitDebug.cpp
@@ -23,7 +23,8 @@
 #include <unwindstack/Elf.h>
 #include <unwindstack/JitDebug.h>
 #include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
+
+#include "MemoryRange.h"
 
 // This implements the JIT Compilation Interface.
 // See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 03658b4..f2dad84 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <stdint.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -27,7 +28,9 @@
 #include <unwindstack/Elf.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
+
+#include "MemoryFileAtOffset.h"
+#include "MemoryRange.h"
 
 namespace unwindstack {
 
@@ -231,11 +234,13 @@
     }
   }
 
-  // If there is a read-only map then a read-execute map that represents the
-  // same elf object, make sure the previous map is using the same elf
-  // object if it hasn't already been set.
-  if (prev_map != nullptr && elf_start_offset != offset && prev_map->offset == elf_start_offset &&
-      prev_map->name == name) {
+  if (!elf->valid()) {
+    elf_start_offset = offset;
+  } else if (prev_map != nullptr && elf_start_offset != offset &&
+             prev_map->offset == elf_start_offset && prev_map->name == name) {
+    // If there is a read-only map then a read-execute map that represents the
+    // same elf object, make sure the previous map is using the same elf
+    // object if it hasn't already been set.
     std::lock_guard<std::mutex> guard(prev_map->mutex_);
     if (prev_map->elf.get() == nullptr) {
       prev_map->elf = elf;
@@ -259,8 +264,8 @@
 }
 
 uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) {
-  uint64_t cur_load_bias = load_bias.load();
-  if (cur_load_bias != static_cast<uint64_t>(-1)) {
+  int64_t cur_load_bias = load_bias.load();
+  if (cur_load_bias != INT64_MAX) {
     return cur_load_bias;
   }
 
@@ -296,7 +301,7 @@
 
 std::string MapInfo::GetBuildID() {
   uintptr_t id = build_id.load();
-  if (build_id != 0) {
+  if (id != 0) {
     return *reinterpret_cast<std::string*>(id);
   }
 
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 5da73e4..0ab68db 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -139,6 +139,9 @@
       if (start == info->start && end == info->end && flags == info->flags && *name == info->name) {
         // No need to check
         search_map_idx = old_map_idx + 1;
+        if (new_map_idx + 1 < maps_.size()) {
+          maps_[new_map_idx + 1]->prev_map = info.get();
+        }
         maps_[new_map_idx] = nullptr;
         total_entries--;
         break;
@@ -149,9 +152,10 @@
       }
 
       // Never delete these maps, they may be in use. The assumption is
-      // that there will only every be a handfull of these so waiting
+      // that there will only every be a handful of these so waiting
       // to destroy them is not too expensive.
       saved_maps_.emplace_back(std::move(info));
+      search_map_idx = old_map_idx + 1;
       maps_[old_map_idx] = nullptr;
       total_entries--;
     }
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index 9904fef..8de3d98 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -32,6 +32,14 @@
 #include <unwindstack/Memory.h>
 
 #include "Check.h"
+#include "MemoryBuffer.h"
+#include "MemoryCache.h"
+#include "MemoryFileAtOffset.h"
+#include "MemoryLocal.h"
+#include "MemoryOffline.h"
+#include "MemoryOfflineBuffer.h"
+#include "MemoryRange.h"
+#include "MemoryRemote.h"
 
 namespace unwindstack {
 
@@ -168,6 +176,16 @@
   return false;
 }
 
+std::unique_ptr<Memory> Memory::CreateFileMemory(const std::string& path, uint64_t offset) {
+  auto memory = std::make_unique<MemoryFileAtOffset>();
+
+  if (memory->Init(path, offset)) {
+    return memory;
+  }
+
+  return nullptr;
+}
+
 std::shared_ptr<Memory> Memory::CreateProcessMemory(pid_t pid) {
   if (pid == getpid()) {
     return std::shared_ptr<Memory>(new MemoryLocal());
@@ -182,13 +200,18 @@
   return std::shared_ptr<Memory>(new MemoryCache(new MemoryRemote(pid)));
 }
 
+std::shared_ptr<Memory> Memory::CreateOfflineMemory(const uint8_t* data, uint64_t start,
+                                                    uint64_t end) {
+  return std::shared_ptr<Memory>(new MemoryOfflineBuffer(data, start, end));
+}
+
 size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
-  if (addr >= raw_.size()) {
+  if (addr >= size_) {
     return 0;
   }
 
-  size_t bytes_left = raw_.size() - static_cast<size_t>(addr);
-  const unsigned char* actual_base = static_cast<const unsigned char*>(raw_.data()) + addr;
+  size_t bytes_left = size_ - static_cast<size_t>(addr);
+  const unsigned char* actual_base = static_cast<const unsigned char*>(raw_) + addr;
   size_t actual_len = std::min(bytes_left, size);
 
   memcpy(dst, actual_base, actual_len);
@@ -196,7 +219,7 @@
 }
 
 uint8_t* MemoryBuffer::GetPtr(size_t offset) {
-  if (offset < raw_.size()) {
+  if (offset < size_) {
     return &raw_[offset];
   }
   return nullptr;
diff --git a/libunwindstack/MemoryBuffer.h b/libunwindstack/MemoryBuffer.h
new file mode 100644
index 0000000..a91e59f
--- /dev/null
+++ b/libunwindstack/MemoryBuffer.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_BUFFER_H
+#define _LIBUNWINDSTACK_MEMORY_BUFFER_H
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+class MemoryBuffer : public Memory {
+ public:
+  MemoryBuffer() = default;
+  virtual ~MemoryBuffer() { free(raw_); }
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+  uint8_t* GetPtr(size_t offset);
+
+  bool Resize(size_t size) {
+    raw_ = reinterpret_cast<uint8_t*>(realloc(raw_, size));
+    if (raw_ == nullptr) {
+      size_ = 0;
+      return false;
+    }
+    size_ = size;
+    return true;
+  }
+
+  uint64_t Size() { return size_; }
+
+ private:
+  uint8_t* raw_ = nullptr;
+  size_t size_ = 0;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_BUFFER_H
diff --git a/libunwindstack/MemoryCache.h b/libunwindstack/MemoryCache.h
new file mode 100644
index 0000000..769d907
--- /dev/null
+++ b/libunwindstack/MemoryCache.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_CACHE_H
+#define _LIBUNWINDSTACK_MEMORY_CACHE_H
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+class MemoryCache : public Memory {
+ public:
+  MemoryCache(Memory* memory) : impl_(memory) {}
+  virtual ~MemoryCache() = default;
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+  void Clear() override { cache_.clear(); }
+
+ private:
+  constexpr static size_t kCacheBits = 12;
+  constexpr static size_t kCacheMask = (1 << kCacheBits) - 1;
+  constexpr static size_t kCacheSize = 1 << kCacheBits;
+  std::unordered_map<uint64_t, uint8_t[kCacheSize]> cache_;
+
+  std::unique_ptr<Memory> impl_;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_CACHE_H
diff --git a/libunwindstack/MemoryFileAtOffset.h b/libunwindstack/MemoryFileAtOffset.h
new file mode 100644
index 0000000..d136eb4
--- /dev/null
+++ b/libunwindstack/MemoryFileAtOffset.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
+#define _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
+
+#include <stdint.h>
+
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+class MemoryFileAtOffset : public Memory {
+ public:
+  MemoryFileAtOffset() = default;
+  virtual ~MemoryFileAtOffset();
+
+  bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX);
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+  size_t Size() { return size_; }
+
+  void Clear() override;
+
+ protected:
+  size_t size_ = 0;
+  size_t offset_ = 0;
+  uint8_t* data_ = nullptr;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H
diff --git a/libmeminfo/vts/vts_meminfo_test.cpp b/libunwindstack/MemoryLocal.h
similarity index 60%
copy from libmeminfo/vts/vts_meminfo_test.cpp
copy to libunwindstack/MemoryLocal.h
index 3193c31..29aaf12 100644
--- a/libmeminfo/vts/vts_meminfo_test.cpp
+++ b/libunwindstack/MemoryLocal.h
@@ -14,18 +14,23 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
+#ifndef _LIBUNWINDSTACK_MEMORY_LOCAL_H
+#define _LIBUNWINDSTACK_MEMORY_LOCAL_H
 
-#include <meminfo/procmeminfo.h>
+#include <stdint.h>
 
-namespace android {
-namespace meminfo {
+#include <unwindstack/Memory.h>
 
-// /proc/<pid>/smaps_rollup support is required.
-TEST(SmapsRollup, IsSupported) {
-    // Use init's pid for this test since it's the only known pid.
-    ASSERT_TRUE(IsSmapsRollupSupported(1));
-}
+namespace unwindstack {
 
-}  // namespace meminfo
-}  // namespace android
+class MemoryLocal : public Memory {
+ public:
+  MemoryLocal() = default;
+  virtual ~MemoryLocal() = default;
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_LOCAL_H
diff --git a/libunwindstack/MemoryOffline.h b/libunwindstack/MemoryOffline.h
new file mode 100644
index 0000000..789f1a2
--- /dev/null
+++ b/libunwindstack/MemoryOffline.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_H
+#define _LIBUNWINDSTACK_MEMORY_OFFLINE_H
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <unwindstack/Memory.h>
+
+#include "MemoryRange.h"
+
+namespace unwindstack {
+
+class MemoryOffline : public Memory {
+ public:
+  MemoryOffline() = default;
+  virtual ~MemoryOffline() = default;
+
+  bool Init(const std::string& file, uint64_t offset);
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+  std::unique_ptr<MemoryRange> memory_;
+};
+
+class MemoryOfflineParts : public Memory {
+ public:
+  MemoryOfflineParts() = default;
+  virtual ~MemoryOfflineParts();
+
+  void Add(MemoryOffline* memory) { memories_.push_back(memory); }
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+  std::vector<MemoryOffline*> memories_;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_OFFLINE_H
diff --git a/libunwindstack/MemoryOfflineBuffer.h b/libunwindstack/MemoryOfflineBuffer.h
new file mode 100644
index 0000000..64c49a1
--- /dev/null
+++ b/libunwindstack/MemoryOfflineBuffer.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
+#define _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
+
+#include <stdint.h>
+
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+class MemoryOfflineBuffer : public Memory {
+ public:
+  MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end);
+  virtual ~MemoryOfflineBuffer() = default;
+
+  void Reset(const uint8_t* data, uint64_t start, uint64_t end);
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+  const uint8_t* data_;
+  uint64_t start_;
+  uint64_t end_;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H
diff --git a/libunwindstack/MemoryRange.h b/libunwindstack/MemoryRange.h
new file mode 100644
index 0000000..3b4ab5c
--- /dev/null
+++ b/libunwindstack/MemoryRange.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_RANGE_H
+#define _LIBUNWINDSTACK_MEMORY_RANGE_H
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+// MemoryRange maps one address range onto another.
+// The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset,
+// such that range.read(offset) is equivalent to underlying.read(src_begin).
+class MemoryRange : public Memory {
+ public:
+  MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
+              uint64_t offset);
+  virtual ~MemoryRange() = default;
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+  uint64_t offset() { return offset_; }
+  uint64_t length() { return length_; }
+
+ private:
+  std::shared_ptr<Memory> memory_;
+  uint64_t begin_;
+  uint64_t length_;
+  uint64_t offset_;
+};
+
+class MemoryRanges : public Memory {
+ public:
+  MemoryRanges() = default;
+  virtual ~MemoryRanges() = default;
+
+  void Insert(MemoryRange* memory);
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+ private:
+  std::map<uint64_t, std::unique_ptr<MemoryRange>> maps_;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_RANGE_H
diff --git a/libunwindstack/MemoryRemote.h b/libunwindstack/MemoryRemote.h
new file mode 100644
index 0000000..db367d6
--- /dev/null
+++ b/libunwindstack/MemoryRemote.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef _LIBUNWINDSTACK_MEMORY_REMOTE_H
+#define _LIBUNWINDSTACK_MEMORY_REMOTE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <atomic>
+
+#include <unwindstack/Memory.h>
+
+namespace unwindstack {
+
+class MemoryRemote : public Memory {
+ public:
+  MemoryRemote(pid_t pid) : pid_(pid), read_redirect_func_(0) {}
+  virtual ~MemoryRemote() = default;
+
+  size_t Read(uint64_t addr, void* dst, size_t size) override;
+
+  pid_t pid() { return pid_; }
+
+ private:
+  pid_t pid_;
+  std::atomic_uintptr_t read_redirect_func_;
+};
+
+}  // namespace unwindstack
+
+#endif  // _LIBUNWINDSTACK_MEMORY_REMOTE_H
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 885dc94..1b1f7eb 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -127,12 +127,12 @@
   return regs;
 }
 
-bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+bool RegsArm::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
   uint32_t data;
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
     return false;
   }
 
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index e9787aa..1df1dff 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -103,6 +103,7 @@
   fn("sp", regs_[ARM64_REG_SP]);
   fn("lr", regs_[ARM64_REG_LR]);
   fn("pc", regs_[ARM64_REG_PC]);
+  fn("pst", regs_[ARM64_REG_PSTATE]);
 }
 
 Regs* RegsArm64::Read(void* remote_data) {
@@ -113,6 +114,7 @@
   uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
   reg_data[ARM64_REG_PC] = user->pc;
   reg_data[ARM64_REG_SP] = user->sp;
+  reg_data[ARM64_REG_PSTATE] = user->pstate;
   return regs;
 }
 
@@ -124,12 +126,12 @@
   return regs;
 }
 
-bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+bool RegsArm64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
   uint64_t data;
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
     return false;
   }
 
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index f330fe0..ebefe42 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -129,13 +129,13 @@
   return regs;
 }
 
-bool RegsMips::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+bool RegsMips::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
   uint64_t data;
   uint64_t offset = 0;
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
     return false;
   }
 
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 3f67d92..be2fd22 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -127,12 +127,12 @@
   return regs;
 }
 
-bool RegsMips64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+bool RegsMips64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
   uint64_t data;
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->Read(elf_offset, &data, sizeof(data))) {
     return false;
   }
 
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index 9bb39d1..5538fc0 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -119,12 +119,12 @@
   return regs;
 }
 
-bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+bool RegsX86::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
   uint64_t data;
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
+  if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) {
     return false;
   }
 
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 74cd1cb..5b9aa58 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -139,17 +139,17 @@
   return regs;
 }
 
-bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
+bool RegsX86_64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) {
   uint64_t data;
   Memory* elf_memory = elf->memory();
   // Read from elf memory since it is usually more expensive to read from
   // process memory.
-  if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
+  if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
     return false;
   }
 
   uint16_t data2;
-  if (!elf_memory->ReadFully(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
+  if (!elf_memory->ReadFully(elf_offset + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
     return false;
   }
 
diff --git a/libunwindstack/TEST_MAPPING b/libunwindstack/TEST_MAPPING
new file mode 100644
index 0000000..55771c0
--- /dev/null
+++ b/libunwindstack/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libunwindstack_unit_test"
+    }
+  ]
+}
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 37323dc..1bb0319 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -27,8 +27,6 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
-#include <demangle.h>
-
 #include <unwindstack/Elf.h>
 #include <unwindstack/JitDebug.h>
 #include <unwindstack/MapInfo.h>
@@ -36,9 +34,10 @@
 #include <unwindstack/Memory.h>
 #include <unwindstack/Unwinder.h>
 
-#if !defined(NO_LIBDEXFILE_SUPPORT)
 #include <unwindstack/DexFiles.h>
-#endif
+
+// Use the demangler from libc++.
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status);
 
 namespace unwindstack {
 
@@ -63,7 +62,10 @@
   if (info != nullptr) {
     frame->map_start = info->start;
     frame->map_end = info->end;
-    frame->map_elf_start_offset = info->elf_start_offset;
+    // Since this is a dex file frame, the elf_start_offset is not set
+    // by any of the normal code paths. Use the offset of the map since
+    // that matches the actual offset.
+    frame->map_elf_start_offset = info->offset;
     frame->map_exact_offset = info->offset;
     frame->map_load_bias = info->load_bias;
     frame->map_flags = info->flags;
@@ -80,7 +82,7 @@
     return;
   }
 
-#if !defined(NO_LIBDEXFILE_SUPPORT)
+#if defined(DEXFILE_SUPPORT)
   if (dex_files_ == nullptr) {
     return;
   }
@@ -305,7 +307,7 @@
   }
 }
 
-std::string Unwinder::FormatFrame(const FrameData& frame) {
+std::string Unwinder::FormatFrame(const FrameData& frame) const {
   std::string data;
   if (regs_->Is32Bit()) {
     data += android::base::StringPrintf("  #%02zu pc %08" PRIx64, frame.num, frame.rel_pc);
@@ -327,7 +329,14 @@
   }
 
   if (!frame.function_name.empty()) {
-    data += " (" + demangle(frame.function_name.c_str());
+    char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
+    if (demangled_name == nullptr) {
+      data += " (" + frame.function_name;
+    } else {
+      data += " (";
+      data += demangled_name;
+      free(demangled_name);
+    }
     if (frame.function_offset != 0) {
       data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
     }
@@ -344,7 +353,7 @@
   return data;
 }
 
-std::string Unwinder::FormatFrame(size_t frame_num) {
+std::string Unwinder::FormatFrame(size_t frame_num) const {
   if (frame_num >= frames_.size()) {
     return "";
   }
@@ -356,12 +365,10 @@
   jit_debug_ = jit_debug;
 }
 
-#if !defined(NO_LIBDEXFILE_SUPPORT)
 void Unwinder::SetDexFiles(DexFiles* dex_files, ArchEnum arch) {
   dex_files->SetArch(arch);
   dex_files_ = dex_files;
 }
-#endif
 
 bool UnwinderFromPid::Init(ArchEnum arch) {
   if (pid_ == getpid()) {
@@ -379,7 +386,7 @@
   jit_debug_ptr_.reset(new JitDebug(process_memory_));
   jit_debug_ = jit_debug_ptr_.get();
   SetJitDebug(jit_debug_, arch);
-#if !defined(NO_LIBDEXFILE_SUPPORT)
+#if defined(DEXFILE_SUPPORT)
   dex_files_ptr_.reset(new DexFiles(process_memory_));
   dex_files_ = dex_files_ptr_.get();
   SetDexFiles(dex_files_, arch);
diff --git a/libunwindstack/include/unwindstack/DwarfMemory.h b/libunwindstack/include/unwindstack/DwarfMemory.h
index 8dd8d2b..c45699a 100644
--- a/libunwindstack/include/unwindstack/DwarfMemory.h
+++ b/libunwindstack/include/unwindstack/DwarfMemory.h
@@ -49,8 +49,8 @@
   uint64_t cur_offset() { return cur_offset_; }
   void set_cur_offset(uint64_t cur_offset) { cur_offset_ = cur_offset; }
 
-  void set_pc_offset(uint64_t offset) { pc_offset_ = offset; }
-  void clear_pc_offset() { pc_offset_ = static_cast<uint64_t>(-1); }
+  void set_pc_offset(int64_t offset) { pc_offset_ = offset; }
+  void clear_pc_offset() { pc_offset_ = INT64_MAX; }
 
   void set_data_offset(uint64_t offset) { data_offset_ = offset; }
   void clear_data_offset() { data_offset_ = static_cast<uint64_t>(-1); }
@@ -65,7 +65,7 @@
   Memory* memory_;
   uint64_t cur_offset_ = 0;
 
-  uint64_t pc_offset_ = static_cast<uint64_t>(-1);
+  int64_t pc_offset_ = INT64_MAX;
   uint64_t data_offset_ = static_cast<uint64_t>(-1);
   uint64_t func_offset_ = static_cast<uint64_t>(-1);
   uint64_t text_offset_ = static_cast<uint64_t>(-1);
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index e9942de..c244749 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -86,7 +86,7 @@
   DwarfErrorCode LastErrorCode() { return last_error_.code; }
   uint64_t LastErrorAddress() { return last_error_.address; }
 
-  virtual bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) = 0;
+  virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0;
 
   virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
 
@@ -125,10 +125,16 @@
   DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
   virtual ~DwarfSectionImpl() = default;
 
+  bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
+
   const DwarfCie* GetCieFromOffset(uint64_t offset);
 
   const DwarfFde* GetFdeFromOffset(uint64_t offset);
 
+  const DwarfFde* GetFdeFromPc(uint64_t pc) override;
+
+  void GetFdes(std::vector<const DwarfFde*>* fdes) override;
+
   bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
 
   bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
@@ -139,6 +145,8 @@
   bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
 
  protected:
+  bool GetNextCieOrFde(const DwarfFde** fde_entry);
+
   bool FillInCieHeader(DwarfCie* cie);
 
   bool FillInCie(DwarfCie* cie);
@@ -150,43 +158,13 @@
   bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
                       RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
 
-  uint64_t load_bias_ = 0;
-  uint64_t entries_offset_ = 0;
-  uint64_t entries_end_ = 0;
-  uint64_t pc_offset_ = 0;
-};
-
-template <typename AddressType>
-class DwarfSectionImplNoHdr : public DwarfSectionImpl<AddressType> {
- public:
-  // Add these so that the protected members of DwarfSectionImpl
-  // can be accessed without needing a this->.
-  using DwarfSectionImpl<AddressType>::memory_;
-  using DwarfSectionImpl<AddressType>::pc_offset_;
-  using DwarfSectionImpl<AddressType>::entries_offset_;
-  using DwarfSectionImpl<AddressType>::entries_end_;
-  using DwarfSectionImpl<AddressType>::last_error_;
-  using DwarfSectionImpl<AddressType>::load_bias_;
-  using DwarfSectionImpl<AddressType>::cie_entries_;
-  using DwarfSectionImpl<AddressType>::fde_entries_;
-  using DwarfSectionImpl<AddressType>::cie32_value_;
-  using DwarfSectionImpl<AddressType>::cie64_value_;
-
-  DwarfSectionImplNoHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
-  virtual ~DwarfSectionImplNoHdr() = default;
-
-  bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
-
-  const DwarfFde* GetFdeFromPc(uint64_t pc) override;
-
-  void GetFdes(std::vector<const DwarfFde*>* fdes) override;
-
- protected:
-  bool GetNextCieOrFde(DwarfFde** fde_entry);
-
   void InsertFde(const DwarfFde* fde);
 
+  int64_t section_bias_ = 0;
+  uint64_t entries_offset_ = 0;
+  uint64_t entries_end_ = 0;
   uint64_t next_entries_offset_ = 0;
+  uint64_t pc_offset_ = 0;
 
   std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
 };
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 56bf318..472ed92 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -63,7 +63,7 @@
 
   bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
 
-  bool GetGlobalVariable(const std::string& name, uint64_t* memory_address);
+  bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset);
 
   uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
 
@@ -75,7 +75,7 @@
 
   std::string GetBuildID();
 
-  uint64_t GetLoadBias() { return load_bias_; }
+  int64_t GetLoadBias() { return load_bias_; }
 
   bool IsValidPc(uint64_t pc);
 
@@ -101,7 +101,7 @@
 
   static bool GetInfo(Memory* memory, uint64_t* size);
 
-  static uint64_t GetLoadBias(Memory* memory);
+  static int64_t GetLoadBias(Memory* memory);
 
   static std::string GetBuildID(Memory* memory);
 
@@ -116,7 +116,7 @@
 
  protected:
   bool valid_ = false;
-  uint64_t load_bias_ = 0;
+  int64_t load_bias_ = 0;
   std::unique_ptr<ElfInterface> interface_;
   std::unique_ptr<Memory> memory_;
   uint32_t machine_type_;
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index dbd917d..0c39b23 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -52,9 +52,9 @@
   ElfInterface(Memory* memory) : memory_(memory) {}
   virtual ~ElfInterface();
 
-  virtual bool Init(uint64_t* load_bias) = 0;
+  virtual bool Init(int64_t* load_bias) = 0;
 
-  virtual void InitHeaders(uint64_t load_bias) = 0;
+  virtual void InitHeaders() = 0;
 
   virtual std::string GetSoname() = 0;
 
@@ -77,13 +77,19 @@
   void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; }
 
   uint64_t dynamic_offset() { return dynamic_offset_; }
-  uint64_t dynamic_vaddr() { return dynamic_vaddr_; }
-  uint64_t dynamic_size() { return dynamic_size_; }
+  uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; }
+  uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; }
+  uint64_t data_offset() { return data_offset_; }
+  uint64_t data_vaddr_start() { return data_vaddr_start_; }
+  uint64_t data_vaddr_end() { return data_vaddr_end_; }
   uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; }
+  int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; }
   uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; }
   uint64_t eh_frame_offset() { return eh_frame_offset_; }
+  int64_t eh_frame_section_bias() { return eh_frame_section_bias_; }
   uint64_t eh_frame_size() { return eh_frame_size_; }
   uint64_t debug_frame_offset() { return debug_frame_offset_; }
+  int64_t debug_frame_section_bias() { return debug_frame_section_bias_; }
   uint64_t debug_frame_size() { return debug_frame_size_; }
   uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; }
   uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; }
@@ -98,20 +104,20 @@
   uint64_t LastErrorAddress() { return last_error_.address; }
 
   template <typename EhdrType, typename PhdrType>
-  static uint64_t GetLoadBias(Memory* memory);
+  static int64_t GetLoadBias(Memory* memory);
 
   template <typename EhdrType, typename ShdrType, typename NhdrType>
   static std::string ReadBuildIDFromMemory(Memory* memory);
 
  protected:
   template <typename AddressType>
-  void InitHeadersWithTemplate(uint64_t load_bias);
+  void InitHeadersWithTemplate();
 
   template <typename EhdrType, typename PhdrType, typename ShdrType>
-  bool ReadAllHeaders(uint64_t* load_bias);
+  bool ReadAllHeaders(int64_t* load_bias);
 
   template <typename EhdrType, typename PhdrType>
-  void ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias);
+  void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias);
 
   template <typename EhdrType, typename ShdrType>
   void ReadSectionHeaders(const EhdrType& ehdr);
@@ -138,16 +144,23 @@
 
   // Stored elf data.
   uint64_t dynamic_offset_ = 0;
-  uint64_t dynamic_vaddr_ = 0;
-  uint64_t dynamic_size_ = 0;
+  uint64_t dynamic_vaddr_start_ = 0;
+  uint64_t dynamic_vaddr_end_ = 0;
+
+  uint64_t data_offset_ = 0;
+  uint64_t data_vaddr_start_ = 0;
+  uint64_t data_vaddr_end_ = 0;
 
   uint64_t eh_frame_hdr_offset_ = 0;
+  int64_t eh_frame_hdr_section_bias_ = 0;
   uint64_t eh_frame_hdr_size_ = 0;
 
   uint64_t eh_frame_offset_ = 0;
+  int64_t eh_frame_section_bias_ = 0;
   uint64_t eh_frame_size_ = 0;
 
   uint64_t debug_frame_offset_ = 0;
+  int64_t debug_frame_section_bias_ = 0;
   uint64_t debug_frame_size_ = 0;
 
   uint64_t gnu_debugdata_offset_ = 0;
@@ -175,13 +188,11 @@
   ElfInterface32(Memory* memory) : ElfInterface(memory) {}
   virtual ~ElfInterface32() = default;
 
-  bool Init(uint64_t* load_bias) override {
+  bool Init(int64_t* load_bias) override {
     return ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(load_bias);
   }
 
-  void InitHeaders(uint64_t load_bias) override {
-    ElfInterface::InitHeadersWithTemplate<uint32_t>(load_bias);
-  }
+  void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint32_t>(); }
 
   std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(); }
 
@@ -205,13 +216,11 @@
   ElfInterface64(Memory* memory) : ElfInterface(memory) {}
   virtual ~ElfInterface64() = default;
 
-  bool Init(uint64_t* load_bias) override {
+  bool Init(int64_t* load_bias) override {
     return ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(load_bias);
   }
 
-  void InitHeaders(uint64_t load_bias) override {
-    ElfInterface::InitHeadersWithTemplate<uint64_t>(load_bias);
-  }
+  void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint64_t>(); }
 
   std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(); }
 
diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h
index a7e6c15..b9bb141 100644
--- a/libunwindstack/include/unwindstack/Global.h
+++ b/libunwindstack/include/unwindstack/Global.h
@@ -45,7 +45,7 @@
   ArchEnum arch() { return arch_; }
 
  protected:
-  uint64_t GetVariableOffset(MapInfo* info, const std::string& variable);
+  bool Searchable(const std::string& name);
   void FindAndReadVariable(Maps* maps, const char* variable);
 
   virtual bool ReadVariableData(uint64_t offset) = 0;
diff --git a/libunwindstack/include/unwindstack/MachineArm64.h b/libunwindstack/include/unwindstack/MachineArm64.h
index e8b778b..e953335 100644
--- a/libunwindstack/include/unwindstack/MachineArm64.h
+++ b/libunwindstack/include/unwindstack/MachineArm64.h
@@ -55,6 +55,7 @@
   ARM64_REG_R30,
   ARM64_REG_R31,
   ARM64_REG_PC,
+  ARM64_REG_PSTATE,
   ARM64_REG_LAST,
 
   ARM64_REG_SP = ARM64_REG_R31,
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 025fd98..8f0c516 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -25,10 +25,11 @@
 #include <string>
 
 #include <unwindstack/Elf.h>
-#include <unwindstack/Memory.h>
 
 namespace unwindstack {
 
+class MemoryFileAtOffset;
+
 struct MapInfo {
   MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
           const char* name)
@@ -38,7 +39,7 @@
         flags(flags),
         name(name),
         prev_map(map_info),
-        load_bias(static_cast<uint64_t>(-1)),
+        load_bias(INT64_MAX),
         build_id(0) {}
   MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
           const std::string& name)
@@ -48,7 +49,7 @@
         flags(flags),
         name(name),
         prev_map(map_info),
-        load_bias(static_cast<uint64_t>(-1)),
+        load_bias(INT64_MAX),
         build_id(0) {}
   ~MapInfo();
 
@@ -58,17 +59,20 @@
   uint16_t flags = 0;
   std::string name;
   std::shared_ptr<Elf> elf;
+  // The offset of the beginning of this mapping to the beginning of the
+  // ELF file.
+  // elf_offset == offset - elf_start_offset.
   // This value is only non-zero if the offset is non-zero but there is
   // no elf signature found at that offset.
   uint64_t elf_offset = 0;
-  // This value is the offset from the map in memory that is the start
-  // of the elf. This is not equal to offset when the linker splits
+  // This value is the offset into the file of the map in memory that is the
+  // start of the elf. This is not equal to offset when the linker splits
   // shared libraries into a read-only and read-execute map.
   uint64_t elf_start_offset = 0;
 
   MapInfo* prev_map = nullptr;
 
-  std::atomic_uint64_t load_bias;
+  std::atomic_int64_t load_bias;
 
   // This is a pointer to a new'd std::string.
   // Using an atomic value means that we don't need to lock and will
diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h
index 1784394..e53f367 100644
--- a/libunwindstack/include/unwindstack/Maps.h
+++ b/libunwindstack/include/unwindstack/Maps.h
@@ -105,7 +105,7 @@
 
   const std::string GetMapsFile() const override;
 
- private:
+ protected:
   std::vector<std::unique_ptr<MapInfo>> saved_maps_;
 };
 
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index b3beb6e..3106564 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -21,12 +21,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <atomic>
-#include <map>
 #include <memory>
 #include <string>
-#include <unordered_map>
-#include <vector>
 
 namespace unwindstack {
 
@@ -37,6 +33,9 @@
 
   static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid);
   static std::shared_ptr<Memory> CreateProcessMemoryCached(pid_t pid);
+  static std::shared_ptr<Memory> CreateOfflineMemory(const uint8_t* data, uint64_t start,
+                                                     uint64_t end);
+  static std::unique_ptr<Memory> CreateFileMemory(const std::string& path, uint64_t offset);
 
   virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX);
 
@@ -55,157 +54,6 @@
   }
 };
 
-class MemoryCache : public Memory {
- public:
-  MemoryCache(Memory* memory) : impl_(memory) {}
-  virtual ~MemoryCache() = default;
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
-  void Clear() override { cache_.clear(); }
-
- private:
-  constexpr static size_t kCacheBits = 12;
-  constexpr static size_t kCacheMask = (1 << kCacheBits) - 1;
-  constexpr static size_t kCacheSize = 1 << kCacheBits;
-  std::unordered_map<uint64_t, uint8_t[kCacheSize]> cache_;
-
-  std::unique_ptr<Memory> impl_;
-};
-
-class MemoryBuffer : public Memory {
- public:
-  MemoryBuffer() = default;
-  virtual ~MemoryBuffer() = default;
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
-  uint8_t* GetPtr(size_t offset);
-
-  void Resize(size_t size) { raw_.resize(size); }
-
-  uint64_t Size() { return raw_.size(); }
-
- private:
-  std::vector<uint8_t> raw_;
-};
-
-class MemoryFileAtOffset : public Memory {
- public:
-  MemoryFileAtOffset() = default;
-  virtual ~MemoryFileAtOffset();
-
-  bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX);
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
-  size_t Size() { return size_; }
-
-  void Clear() override;
-
- protected:
-  size_t size_ = 0;
-  size_t offset_ = 0;
-  uint8_t* data_ = nullptr;
-};
-
-class MemoryRemote : public Memory {
- public:
-  MemoryRemote(pid_t pid) : pid_(pid), read_redirect_func_(0) {}
-  virtual ~MemoryRemote() = default;
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
-  pid_t pid() { return pid_; }
-
- private:
-  pid_t pid_;
-  std::atomic_uintptr_t read_redirect_func_;
-};
-
-class MemoryLocal : public Memory {
- public:
-  MemoryLocal() = default;
-  virtual ~MemoryLocal() = default;
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-};
-
-// MemoryRange maps one address range onto another.
-// The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset,
-// such that range.read(offset) is equivalent to underlying.read(src_begin).
-class MemoryRange : public Memory {
- public:
-  MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
-              uint64_t offset);
-  virtual ~MemoryRange() = default;
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
-  uint64_t offset() { return offset_; }
-  uint64_t length() { return length_; }
-
- private:
-  std::shared_ptr<Memory> memory_;
-  uint64_t begin_;
-  uint64_t length_;
-  uint64_t offset_;
-};
-
-class MemoryRanges : public Memory {
- public:
-  MemoryRanges() = default;
-  virtual ~MemoryRanges() = default;
-
-  void Insert(MemoryRange* memory);
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
-  std::map<uint64_t, std::unique_ptr<MemoryRange>> maps_;
-};
-
-class MemoryOffline : public Memory {
- public:
-  MemoryOffline() = default;
-  virtual ~MemoryOffline() = default;
-
-  bool Init(const std::string& file, uint64_t offset);
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
-  std::unique_ptr<MemoryRange> memory_;
-};
-
-class MemoryOfflineBuffer : public Memory {
- public:
-  MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end);
-  virtual ~MemoryOfflineBuffer() = default;
-
-  void Reset(const uint8_t* data, uint64_t start, uint64_t end);
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
-  const uint8_t* data_;
-  uint64_t start_;
-  uint64_t end_;
-};
-
-class MemoryOfflineParts : public Memory {
- public:
-  MemoryOfflineParts() = default;
-  virtual ~MemoryOfflineParts();
-
-  void Add(MemoryOffline* memory) { memories_.push_back(memory); }
-
-  size_t Read(uint64_t addr, void* dst, size_t size) override;
-
- private:
-  std::vector<MemoryOffline*> memories_;
-};
-
 }  // namespace unwindstack
 
 #endif  // _LIBUNWINDSTACK_MEMORY_H
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 1c2a81c..4f761b4 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -66,7 +66,7 @@
 
   virtual uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) = 0;
 
-  virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
+  virtual bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) = 0;
 
   virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
 
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index 44f6744..aa029be 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -40,7 +40,7 @@
 
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
-  bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
 
   void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index a72f91f..5cd7e5b 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -40,7 +40,7 @@
 
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
-  bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
 
   void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index c9dd202..8164a15 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -40,7 +40,7 @@
 
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
-  bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
 
   void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 7c42812..c982542 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -40,7 +40,7 @@
 
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
-  bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
 
   void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
 
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index d19e449..2323a4f 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -41,7 +41,7 @@
 
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
-  bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
 
   void SetFromUcontext(x86_ucontext_t* ucontext);
 
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index dc9a220..3e919a4 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -41,7 +41,7 @@
 
   bool SetPcFromReturnAddress(Memory* process_memory) override;
 
-  bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
+  bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override;
 
   void SetFromUcontext(x86_64_ucontext_t* ucontext);
 
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 52b3578..67762c0 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -77,7 +77,7 @@
   void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
               const std::vector<std::string>* map_suffixes_to_ignore = nullptr);
 
-  size_t NumFrames() { return frames_.size(); }
+  size_t NumFrames() const { return frames_.size(); }
 
   const std::vector<FrameData>& frames() { return frames_; }
 
@@ -87,8 +87,8 @@
     return frames;
   }
 
-  std::string FormatFrame(size_t frame_num);
-  std::string FormatFrame(const FrameData& frame);
+  std::string FormatFrame(size_t frame_num) const;
+  std::string FormatFrame(const FrameData& frame) const;
 
   void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
 
@@ -107,9 +107,7 @@
 
   void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; }
 
-#if !defined(NO_LIBDEXFILE_SUPPORT)
   void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
-#endif
 
   bool elf_from_memory_not_file() { return elf_from_memory_not_file_; }
 
@@ -128,9 +126,7 @@
   std::vector<FrameData> frames_;
   std::shared_ptr<Memory> process_memory_;
   JitDebug* jit_debug_ = nullptr;
-#if !defined(NO_LIBDEXFILE_SUPPORT)
   DexFiles* dex_files_ = nullptr;
-#endif
   bool resolve_names_ = true;
   bool embedded_soname_ = true;
   bool display_build_id_ = false;
@@ -151,9 +147,7 @@
   pid_t pid_;
   std::unique_ptr<Maps> maps_ptr_;
   std::unique_ptr<JitDebug> jit_debug_ptr_;
-#if !defined(NO_LIBDEXFILE_SUPPORT)
   std::unique_ptr<DexFiles> dex_files_ptr_;
-#endif
 };
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp
index 5f3d1ea..69a7816 100644
--- a/libunwindstack/tests/ArmExidxDecodeTest.cpp
+++ b/libunwindstack/tests/ArmExidxDecodeTest.cpp
@@ -1662,7 +1662,7 @@
   ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
 }
 
-INSTANTIATE_TEST_CASE_P(, ArmExidxDecodeTest,
-                        ::testing::Values("logging", "register_logging", "no_logging"));
+INSTANTIATE_TEST_SUITE_P(Unwindstack, ArmExidxDecodeTest,
+                         ::testing::Values("logging", "register_logging", "no_logging"));
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index 1ea9e5c..0dd3af6 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -36,14 +36,18 @@
 
 class DexFilesTest : public ::testing::Test {
  protected:
-  void CreateFakeElf(MapInfo* map_info) {
+  void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
+                     uint64_t data_vaddr, uint64_t data_size) {
     MemoryFake* memory = new MemoryFake;
     ElfFake* elf = new ElfFake(memory);
     elf->FakeSetValid(true);
     ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
     elf->FakeSetInterface(interface);
 
-    interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
+    interface->FakeSetGlobalVariable("__dex_debug_descriptor", global_offset);
+    interface->FakeSetDataOffset(data_offset);
+    interface->FakeSetDataVaddrStart(data_vaddr);
+    interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
     map_info->elf.reset(elf);
   }
 
@@ -54,11 +58,11 @@
     maps_.reset(
         new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
                        "4000-6000 r--s 00000000 00:00 0 /fake/elf\n"
-                       "6000-8000 -wxs 00000000 00:00 0 /fake/elf\n"
+                       "6000-8000 -wxs 00002000 00:00 0 /fake/elf\n"
                        "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
-                       "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
+                       "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
                        "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
-                       "100000-110000 rw-p 0001000 00:00 0 /fake/elf3\n"
+                       "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n"
                        "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n"
                        "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n"));
     ASSERT_TRUE(maps_->Parse());
@@ -66,17 +70,17 @@
     // Global variable in a section that is not readable.
     MapInfo* map_info = maps_->Get(kMapGlobalNonReadable);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     // Global variable not set by default.
     map_info = maps_->Get(kMapGlobalSetToZero);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     // Global variable set in this map.
     map_info = maps_->Get(kMapGlobal);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000);
   }
 
   void SetUp() override {
@@ -156,7 +160,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -172,7 +176,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x100800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x301000);
   WriteDex(0x301000);
 
@@ -186,7 +190,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0x200100, 0, 0x100000);
   WriteEntry32(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
@@ -203,7 +207,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x100800, 0x200000);
   WriteEntry64(0x200000, 0x200100, 0, 0x100000);
   WriteEntry64(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
@@ -218,7 +222,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -238,7 +242,7 @@
   uint64_t method_offset = 0x124;
   MapInfo* info = maps_->Get(kMapDexFiles);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0x200100, 0, 0x100000);
   WriteEntry32(0x200100, 0, 0x200000, 0x300000);
   WriteDex(0x300000);
@@ -274,9 +278,9 @@
   MapInfo* info = maps_->Get(kMapDexFiles);
 
   // First global variable found, but value is zero.
-  WriteDescriptor32(0xa800, 0);
+  WriteDescriptor32(0xc800, 0);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x100800, 0x200000);
   WriteEntry32(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -289,7 +293,7 @@
   dex_files_->SetArch(ARCH_ARM);
   method_name = "fail";
   method_offset = 0x123;
-  WriteDescriptor32(0xa800, 0x100000);
+  WriteDescriptor32(0xc800, 0x100000);
   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
   EXPECT_EQ("fail", method_name);
   EXPECT_EQ(0x123U, method_offset);
@@ -303,9 +307,9 @@
   MapInfo* info = maps_->Get(kMapDexFiles);
 
   // First global variable found, but value is zero.
-  WriteDescriptor64(0xa800, 0);
+  WriteDescriptor64(0xc800, 0);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x100800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x300000);
   WriteDex(0x300000);
 
@@ -318,7 +322,7 @@
   dex_files_->SetArch(ARCH_ARM64);
   method_name = "fail";
   method_offset = 0x123;
-  WriteDescriptor64(0xa800, 0x100000);
+  WriteDescriptor64(0xc800, 0x100000);
   dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
   EXPECT_EQ("fail", method_name);
   EXPECT_EQ(0x123U, method_offset);
diff --git a/libunwindstack/tests/DwarfCfaLogTest.cpp b/libunwindstack/tests/DwarfCfaLogTest.cpp
index bb2e8f0..def4088 100644
--- a/libunwindstack/tests/DwarfCfaLogTest.cpp
+++ b/libunwindstack/tests/DwarfCfaLogTest.cpp
@@ -66,7 +66,7 @@
   DwarfCie cie_;
   DwarfFde fde_;
 };
-TYPED_TEST_CASE_P(DwarfCfaLogTest);
+TYPED_TEST_SUITE_P(DwarfCfaLogTest);
 
 // NOTE: All class variable references have to be prefaced with this->.
 
@@ -763,17 +763,17 @@
   ASSERT_EQ("", GetFakeLogBuf());
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfCfaLogTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
-                           cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
-                           cfa_advance_loc, cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4,
-                           cfa_undefined, cfa_same, cfa_register, cfa_state,
-                           cfa_state_cfa_offset_restore, cfa_def_cfa, cfa_def_cfa_sf,
-                           cfa_def_cfa_register, cfa_def_cfa_offset, cfa_def_cfa_offset_sf,
-                           cfa_def_cfa_expression, cfa_expression, cfa_val_offset,
-                           cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size,
-                           cfa_gnu_negative_offset_extended, cfa_register_override);
+REGISTER_TYPED_TEST_SUITE_P(DwarfCfaLogTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
+                            cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
+                            cfa_advance_loc, cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4,
+                            cfa_undefined, cfa_same, cfa_register, cfa_state,
+                            cfa_state_cfa_offset_restore, cfa_def_cfa, cfa_def_cfa_sf,
+                            cfa_def_cfa_register, cfa_def_cfa_offset, cfa_def_cfa_offset_sf,
+                            cfa_def_cfa_expression, cfa_expression, cfa_val_offset,
+                            cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size,
+                            cfa_gnu_negative_offset_extended, cfa_register_override);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaLogTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfCfaLogTest, DwarfCfaLogTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaLogTest, DwarfCfaLogTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfCfaTest.cpp b/libunwindstack/tests/DwarfCfaTest.cpp
index 7395b04..9c6ab05 100644
--- a/libunwindstack/tests/DwarfCfaTest.cpp
+++ b/libunwindstack/tests/DwarfCfaTest.cpp
@@ -64,7 +64,7 @@
   DwarfCie cie_;
   DwarfFde fde_;
 };
-TYPED_TEST_CASE_P(DwarfCfaTest);
+TYPED_TEST_SUITE_P(DwarfCfaTest);
 
 // NOTE: All test class variables need to be referenced as this->.
 
@@ -952,16 +952,17 @@
   ASSERT_EQ("", GetFakeLogBuf());
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
-                           cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
-                           cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined,
-                           cfa_same, cfa_register, cfa_state, cfa_state_cfa_offset_restore,
-                           cfa_def_cfa, cfa_def_cfa_sf, cfa_def_cfa_register, cfa_def_cfa_offset,
-                           cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression,
-                           cfa_val_offset, cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size,
-                           cfa_gnu_negative_offset_extended, cfa_register_override);
+REGISTER_TYPED_TEST_SUITE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
+                            cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
+                            cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined,
+                            cfa_same, cfa_register, cfa_state, cfa_state_cfa_offset_restore,
+                            cfa_def_cfa, cfa_def_cfa_sf, cfa_def_cfa_register, cfa_def_cfa_offset,
+                            cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression,
+                            cfa_val_offset, cfa_val_offset_sf, cfa_val_expression,
+                            cfa_gnu_args_size, cfa_gnu_negative_offset_extended,
+                            cfa_register_override);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfCfaTest, DwarfCfaTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaTest, DwarfCfaTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index 120bd73..b6f574a 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -44,7 +44,7 @@
   MemoryFake memory_;
   DwarfDebugFrame<TypeParam>* debug_frame_ = nullptr;
 };
-TYPED_TEST_CASE_P(DwarfDebugFrameTest);
+TYPED_TEST_SUITE_P(DwarfDebugFrameTest);
 
 // NOTE: All test class variables need to be referenced as this->.
 
@@ -812,7 +812,7 @@
   EXPECT_EQ(0xb50U, fde->pc_end);
 }
 
-REGISTER_TYPED_TEST_CASE_P(
+REGISTER_TYPED_TEST_SUITE_P(
     DwarfDebugFrameTest, GetFdes32, GetFdes32_after_GetFdeFromPc, GetFdes32_not_in_section,
     GetFdeFromPc32, GetFdeFromPc32_reverse, GetFdeFromPc32_not_in_section, GetFdes64,
     GetFdes64_after_GetFdeFromPc, GetFdes64_not_in_section, GetFdeFromPc64, GetFdeFromPc64_reverse,
@@ -825,6 +825,6 @@
     GetFdeFromOffset64_lsda_address, GetFdeFromPc_interleaved);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index 9cac6e8..46a25a4 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -42,7 +42,7 @@
   MemoryFake memory_;
   DwarfEhFrame<TypeParam>* eh_frame_ = nullptr;
 };
-TYPED_TEST_CASE_P(DwarfEhFrameTest);
+TYPED_TEST_SUITE_P(DwarfEhFrameTest);
 
 // NOTE: All test class variables need to be referenced as this->.
 
@@ -125,9 +125,9 @@
   EXPECT_EQ(1U, cie->return_address_register);
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, GetFdeCieFromOffset32, GetFdeCieFromOffset64);
+REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameTest, GetFdeCieFromOffset32, GetFdeCieFromOffset64);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameTest, DwarfEhFrameTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index be9e721..6aa3867 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -36,10 +36,8 @@
   ~TestDwarfEhFrameWithHdr() = default;
 
   void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
-  void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
-  void TestSetEntriesEnd(uint64_t end) { this->entries_end_ = end; }
-  void TestSetEntriesDataOffset(uint64_t offset) { this->entries_data_offset_ = offset; }
-  void TestSetCurEntriesOffset(uint64_t offset) { this->cur_entries_offset_ = offset; }
+  void TestSetHdrEntriesOffset(uint64_t offset) { this->hdr_entries_offset_ = offset; }
+  void TestSetHdrEntriesDataOffset(uint64_t offset) { this->hdr_entries_data_offset_ = offset; }
   void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; }
 
   void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
@@ -48,15 +46,11 @@
   }
 
   uint8_t TestGetVersion() { return this->version_; }
-  uint8_t TestGetPtrEncoding() { return this->ptr_encoding_; }
-  uint64_t TestGetPtrOffset() { return this->ptr_offset_; }
   uint8_t TestGetTableEncoding() { return this->table_encoding_; }
   uint64_t TestGetTableEntrySize() { return this->table_entry_size_; }
   uint64_t TestGetFdeCount() { return this->fde_count_; }
-  uint64_t TestGetEntriesOffset() { return this->entries_offset_; }
-  uint64_t TestGetEntriesEnd() { return this->entries_end_; }
-  uint64_t TestGetEntriesDataOffset() { return this->entries_data_offset_; }
-  uint64_t TestGetCurEntriesOffset() { return this->cur_entries_offset_; }
+  uint64_t TestGetHdrEntriesOffset() { return this->hdr_entries_offset_; }
+  uint64_t TestGetHdrEntriesDataOffset() { return this->hdr_entries_data_offset_; }
 };
 
 template <typename TypeParam>
@@ -73,7 +67,7 @@
   MemoryFake memory_;
   TestDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr;
 };
-TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest);
+TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest);
 
 // NOTE: All test class variables need to be referenced as this->.
 
@@ -85,15 +79,11 @@
 
   ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
   EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
-  EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
   EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
   EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
   EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount());
-  EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
-  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
-  EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
-  EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
-  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
+  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
+  EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
 
   // Verify a zero table entry size fails to init.
   this->memory_.SetData8(0x1003, 0x1);
@@ -137,17 +127,14 @@
   this->memory_.SetData32(0x140c, 0x200);
   this->memory_.SetData16(0x1410, 0);
 
+  ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x2000));
   ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
   EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
-  EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
   EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
   EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
   EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
-  EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
-  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
-  EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
-  EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
-  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
+  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
+  EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
 
   const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
   ASSERT_TRUE(fde != nullptr);
@@ -155,6 +142,115 @@
   EXPECT_EQ(0x4700U, fde->pc_end);
 }
 
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias_different_from_eh_frame_bias) {
+  this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
+                                                       DW_EH_PE_pcrel | DW_EH_PE_sdata4});
+  this->memory_.SetData16(0x1004, 0x500);
+  this->memory_.SetData32(0x1006, 1);
+  this->memory_.SetData32(0x100a, 0x2500);
+  this->memory_.SetData32(0x100e, 0x1400);
+
+  // CIE 32 information.
+  this->memory_.SetData32(0x1300, 0xfc);
+  this->memory_.SetData32(0x1304, 0);
+  this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
+
+  // FDE 32 information.
+  this->memory_.SetData32(0x1400, 0xfc);
+  this->memory_.SetData32(0x1404, 0x104);
+  this->memory_.SetData32(0x1408, 0x20f8);
+  this->memory_.SetData32(0x140c, 0x200);
+  this->memory_.SetData16(0x1410, 0);
+
+  ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x1000));
+  ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
+  EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
+  EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
+  EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
+  EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
+  EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset());
+  EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset());
+
+  const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
+  ASSERT_TRUE(fde != nullptr);
+  EXPECT_EQ(0x4500U, fde->pc_start);
+  EXPECT_EQ(0x4700U, fde->pc_end);
+}
+
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_wtih_empty_fde) {
+  this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
+                                                       DW_EH_PE_pcrel | DW_EH_PE_sdata4});
+  this->memory_.SetData16(0x1004, 0x500);
+  this->memory_.SetData32(0x1006, 1);
+  this->memory_.SetData32(0x100a, 0x2500);
+  this->memory_.SetData32(0x100e, 0x1400);
+
+  // CIE 32 information.
+  this->memory_.SetData32(0x1300, 0xfc);
+  this->memory_.SetData32(0x1304, 0);
+  this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
+
+  // FDE 32 information.
+  this->memory_.SetData32(0x1400, 0xfc);
+  this->memory_.SetData32(0x1404, 0x104);
+  this->memory_.SetData32(0x1408, 0x30f8);
+  this->memory_.SetData32(0x140c, 0);
+  this->memory_.SetData16(0x1410, 0);
+
+  // FDE 32 information.
+  this->memory_.SetData32(0x1500, 0xfc);
+  this->memory_.SetData32(0x1504, 0x204);
+  this->memory_.SetData32(0x1508, 0x2ff8);
+  this->memory_.SetData32(0x150c, 0x200);
+  this->memory_.SetData16(0x1510, 0);
+
+  ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0));
+  ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
+
+  const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
+  ASSERT_TRUE(fde != nullptr);
+  EXPECT_EQ(0x4500U, fde->pc_start);
+  EXPECT_EQ(0x4700U, fde->pc_end);
+}
+
+TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes_with_empty_fde) {
+  this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
+                                                       DW_EH_PE_pcrel | DW_EH_PE_sdata4});
+  this->memory_.SetData16(0x1004, 0x500);
+  this->memory_.SetData32(0x1006, 1);
+  this->memory_.SetData32(0x100a, 0x2500);
+  this->memory_.SetData32(0x100e, 0x1400);
+
+  // CIE 32 information.
+  this->memory_.SetData32(0x1300, 0xfc);
+  this->memory_.SetData32(0x1304, 0);
+  this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
+
+  // FDE 32 information.
+  this->memory_.SetData32(0x1400, 0xfc);
+  this->memory_.SetData32(0x1404, 0x104);
+  this->memory_.SetData32(0x1408, 0x30f8);
+  this->memory_.SetData32(0x140c, 0);
+  this->memory_.SetData16(0x1410, 0);
+
+  // FDE 32 information.
+  this->memory_.SetData32(0x1500, 0xfc);
+  this->memory_.SetData32(0x1504, 0x204);
+  this->memory_.SetData32(0x1508, 0x2ff8);
+  this->memory_.SetData32(0x150c, 0x200);
+  this->memory_.SetData16(0x1510, 0);
+
+  ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0));
+  ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
+
+  std::vector<const DwarfFde*> fdes;
+  this->eh_frame_->GetFdes(&fdes);
+  ASSERT_FALSE(fdes.empty());
+  ASSERT_EQ(1U, fdes.size());
+  EXPECT_EQ(0x4500U, fdes[0]->pc_start);
+  EXPECT_EQ(0x4700U, fdes[0]->pc_end);
+}
+
 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes) {
   this->memory_.SetMemory(
       0x1000, std::vector<uint8_t>{1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
@@ -220,7 +316,7 @@
 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
   this->eh_frame_->TestSetTableEntrySize(0x10);
   this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
-  this->eh_frame_->TestSetEntriesOffset(0x1000);
+  this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
 
   ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
   ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
@@ -233,8 +329,8 @@
 // We are assuming that pc rel, is really relative to the load_bias.
 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
   this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4);
-  this->eh_frame_->TestSetEntriesOffset(0x1000);
-  this->eh_frame_->TestSetEntriesDataOffset(0x3000);
+  this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
+  this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
   this->eh_frame_->TestSetTableEntrySize(0x10);
 
   this->memory_.SetData32(0x1040, 0x340);
@@ -248,8 +344,8 @@
 
 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) {
   this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4);
-  this->eh_frame_->TestSetEntriesOffset(0x1000);
-  this->eh_frame_->TestSetEntriesDataOffset(0x3000);
+  this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
+  this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000);
   this->eh_frame_->TestSetTableEntrySize(0x10);
 
   this->memory_.SetData32(0x1040, 0x340);
@@ -263,7 +359,7 @@
 
 TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) {
   this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
-  this->eh_frame_->TestSetEntriesOffset(0x1000);
+  this->eh_frame_->TestSetHdrEntriesOffset(0x1000);
   this->eh_frame_->TestSetTableEntrySize(0x10);
 
   this->memory_.SetData32(0x1040, 0x340);
@@ -446,14 +542,16 @@
   ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes,
-                           GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
-                           GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
-                           GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail,
-                           GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search,
-                           GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
+REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias,
+                            Init_non_zero_load_bias_different_from_eh_frame_bias,
+                            GetFdeFromPc_wtih_empty_fde, GetFdes_with_empty_fde, GetFdes,
+                            GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
+                            GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
+                            GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail,
+                            GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search,
+                            GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfOpLogTest.cpp b/libunwindstack/tests/DwarfOpLogTest.cpp
index 3f09dd8..8dbf6e8 100644
--- a/libunwindstack/tests/DwarfOpLogTest.cpp
+++ b/libunwindstack/tests/DwarfOpLogTest.cpp
@@ -48,7 +48,7 @@
   std::unique_ptr<DwarfMemory> mem_;
   std::unique_ptr<DwarfOp<TypeParam>> op_;
 };
-TYPED_TEST_CASE_P(DwarfOpLogTest);
+TYPED_TEST_SUITE_P(DwarfOpLogTest);
 
 TYPED_TEST_P(DwarfOpLogTest, multiple_ops) {
   // Multi operation opcodes.
@@ -65,9 +65,9 @@
   ASSERT_EQ(expected, lines);
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfOpLogTest, multiple_ops);
+REGISTER_TYPED_TEST_SUITE_P(DwarfOpLogTest, multiple_ops);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfOpLogTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpLogTest, DwarfOpLogTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfOpLogTest, DwarfOpLogTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index d424d5f..0e2d91a 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -48,7 +48,7 @@
   std::unique_ptr<DwarfMemory> mem_;
   std::unique_ptr<DwarfOp<TypeParam>> op_;
 };
-TYPED_TEST_CASE_P(DwarfOpTest);
+TYPED_TEST_SUITE_P(DwarfOpTest);
 
 TYPED_TEST_P(DwarfOpTest, decode) {
   // Memory error.
@@ -1571,15 +1571,16 @@
   EXPECT_FALSE(this->op_->dex_pc_set());
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfOpTest, decode, eval, illegal_opcode, not_implemented, op_addr,
-                           op_deref, op_deref_size, const_unsigned, const_signed, const_uleb,
-                           const_sleb, op_dup, op_drop, op_over, op_pick, op_swap, op_rot, op_abs,
-                           op_and, op_div, op_minus, op_mod, op_mul, op_neg, op_not, op_or, op_plus,
-                           op_plus_uconst, op_shl, op_shr, op_shra, op_xor, op_bra,
-                           compare_opcode_stack_error, compare_opcodes, op_skip, op_lit, op_reg,
-                           op_regx, op_breg, op_breg_invalid_register, op_bregx, op_nop, is_dex_pc);
+REGISTER_TYPED_TEST_SUITE_P(DwarfOpTest, decode, eval, illegal_opcode, not_implemented, op_addr,
+                            op_deref, op_deref_size, const_unsigned, const_signed, const_uleb,
+                            const_sleb, op_dup, op_drop, op_over, op_pick, op_swap, op_rot, op_abs,
+                            op_and, op_div, op_minus, op_mod, op_mul, op_neg, op_not, op_or,
+                            op_plus, op_plus_uconst, op_shl, op_shr, op_shra, op_xor, op_bra,
+                            compare_opcode_stack_error, compare_opcodes, op_skip, op_lit, op_reg,
+                            op_regx, op_breg, op_breg_invalid_register, op_bregx, op_nop,
+                            is_dex_pc);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfOpTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpTest, DwarfOpTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfOpTest, DwarfOpTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 46f555a..cac59b7 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -35,7 +35,7 @@
   TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
   virtual ~TestDwarfSectionImpl() = default;
 
-  bool Init(uint64_t, uint64_t, uint64_t) override { return false; }
+  bool Init(uint64_t, uint64_t, int64_t) override { return false; }
 
   void GetFdes(std::vector<const DwarfFde*>*) override {}
 
@@ -68,7 +68,7 @@
   MemoryFake memory_;
   TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
 };
-TYPED_TEST_CASE_P(DwarfSectionImplTest);
+TYPED_TEST_SUITE_P(DwarfSectionImplTest);
 
 // NOTE: All test class variables need to be referenced as this->.
 
@@ -571,18 +571,18 @@
   ASSERT_EQ("", GetFakeLogBuf());
 }
 
-REGISTER_TYPED_TEST_CASE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
-                           GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
-                           Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
-                           Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
-                           Eval_cfa_register_prev, Eval_cfa_register_from_value,
-                           Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
-                           Eval_invalid_register, Eval_different_reg_locations,
-                           Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
-                           Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
-                           GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
+REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
+                            GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
+                            Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
+                            Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
+                            Eval_cfa_register_prev, Eval_cfa_register_from_value,
+                            Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
+                            Eval_invalid_register, Eval_different_reg_locations,
+                            Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
+                            Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
+                            GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
 
 typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfSectionImplTest, DwarfSectionImplTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index d754fcc..953dc75 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -30,23 +30,24 @@
   MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
   virtual ~MockDwarfSection() = default;
 
-  MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
+  MOCK_METHOD(bool, Init, (uint64_t, uint64_t, int64_t), (override));
 
-  MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
+  MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*),
+              (override));
 
-  MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
+  MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*), (override));
 
-  MOCK_METHOD1(GetFdes, void(std::vector<const DwarfFde*>*));
+  MOCK_METHOD(void, GetFdes, (std::vector<const DwarfFde*>*), (override));
 
-  MOCK_METHOD1(GetFdeFromPc, const DwarfFde*(uint64_t));
+  MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override));
 
-  MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
+  MOCK_METHOD(bool, GetCfaLocationInfo, (uint64_t, const DwarfFde*, dwarf_loc_regs_t*), (override));
 
-  MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
+  MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override));
 
-  MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t));
+  MOCK_METHOD(uint64_t, GetCieOffsetFromFde64, (uint64_t), (override));
 
-  MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t));
+  MOCK_METHOD(uint64_t, AdjustPcFromFde, (uint64_t), (override));
 };
 
 class DwarfSectionTest : public ::testing::Test {
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 07fd6f6..5735858 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -31,7 +31,7 @@
 
 class ElfCacheTest : public ::testing::Test {
  protected:
-  static void SetUpTestCase() { memory_.reset(new MemoryFake); }
+  static void SetUpTestSuite() { memory_.reset(new MemoryFake); }
 
   void SetUp() override { Elf::SetCachingEnabled(true); }
 
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index bd3083c..fc90dab 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -66,8 +66,8 @@
   ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {}
   virtual ~ElfInterfaceFake() = default;
 
-  bool Init(uint64_t*) override { return false; }
-  void InitHeaders(uint64_t) override {}
+  bool Init(int64_t*) override { return false; }
+  void InitHeaders() override {}
   std::string GetSoname() override { return fake_soname_; }
 
   bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
@@ -97,6 +97,17 @@
 
   void FakeSetErrorAddress(uint64_t address) { last_error_.address = address; }
 
+  void FakeSetDataOffset(uint64_t offset) { data_offset_ = offset; }
+  void FakeSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; }
+  void FakeSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; }
+
+  void FakeSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
+  void FakeSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
+  void FakeSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
+
+  void FakeSetGnuDebugdataOffset(uint64_t offset) { gnu_debugdata_offset_ = offset; }
+  void FakeSetGnuDebugdataSize(uint64_t size) { gnu_debugdata_size_ = size; }
+
  private:
   std::unordered_map<std::string, uint64_t> globals_;
   std::string fake_build_id_;
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index cdc927a..3cf90fe 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -112,6 +112,21 @@
   template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
   void InitSectionHeadersOffsets();
 
+  template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+  void InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset,
+                                                   int64_t expected_bias);
+
+  template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+  void InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr, uint64_t offset,
+                                                      int64_t expected_bias);
+
+  template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+  void InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr, uint64_t offset,
+                                                      int64_t expected_bias);
+
+  template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
+  void CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias);
+
   template <typename Sym>
   void InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset,
                uint64_t sym_offset, const char* name);
@@ -131,6 +146,12 @@
   template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
   void BuildIDSectionTooSmallForHeader();
 
+  template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
+  void CheckLoadBiasInFirstPhdr(int64_t load_bias);
+
+  template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
+  void CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, int64_t load_bias);
+
   MemoryFake memory_;
 };
 
@@ -166,9 +187,9 @@
   phdr.p_align = 0x1000;
   memory_.SetMemory(0x100, &phdr, sizeof(phdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0x2000U, load_bias);
+  EXPECT_EQ(0x2000, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(1U, pt_loads.size());
@@ -178,11 +199,11 @@
   ASSERT_EQ(0x10000U, load_data.table_size);
 }
 
-TEST_F(ElfInterfaceTest, elf32_single_pt_load) {
+TEST_F(ElfInterfaceTest, single_pt_load_32) {
   SinglePtLoad<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_single_pt_load) {
+TEST_F(ElfInterfaceTest, single_pt_load_64) {
   SinglePtLoad<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
 }
 
@@ -222,9 +243,9 @@
   phdr.p_align = 0x1002;
   memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0x2000U, load_bias);
+  EXPECT_EQ(0x2000, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(3U, pt_loads.size());
@@ -245,11 +266,11 @@
   ASSERT_EQ(0x10002U, load_data.table_size);
 }
 
-TEST_F(ElfInterfaceTest, elf32_multiple_executable_pt_loads) {
+TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_32) {
   MultipleExecutablePtLoads<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_multiple_executable_pt_loads) {
+TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_64) {
   MultipleExecutablePtLoads<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
 }
 
@@ -289,9 +310,9 @@
   phdr.p_align = 0x1002;
   memory_.SetMemory(0x100 + 2 * (sizeof(phdr) + 100), &phdr, sizeof(phdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0x2000U, load_bias);
+  EXPECT_EQ(0x2000, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(3U, pt_loads.size());
@@ -312,12 +333,12 @@
   ASSERT_EQ(0x10002U, load_data.table_size);
 }
 
-TEST_F(ElfInterfaceTest, elf32_multiple_executable_pt_loads_increments_not_size_of_phdr) {
+TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_32) {
   MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn,
                                                    ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_multiple_executable_pt_loads_increments_not_size_of_phdr) {
+TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_64) {
   MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn,
                                                    ElfInterface64>();
 }
@@ -358,9 +379,9 @@
   phdr.p_align = 0x1002;
   memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0x1001, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(1U, pt_loads.size());
@@ -371,11 +392,11 @@
   ASSERT_EQ(0x10001U, load_data.table_size);
 }
 
-TEST_F(ElfInterfaceTest, elf32_non_executable_pt_loads) {
+TEST_F(ElfInterfaceTest, non_executable_pt_loads_32) {
   NonExecutablePtLoads<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_non_executable_pt_loads) {
+TEST_F(ElfInterfaceTest, non_executable_pt_loads_64) {
   NonExecutablePtLoads<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
 }
 
@@ -428,11 +449,10 @@
   memset(&phdr, 0, sizeof(phdr));
   phdr.p_type = PT_GNU_EH_FRAME;
   memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
-  phdr_offset += sizeof(phdr);
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0x2000U, load_bias);
+  EXPECT_EQ(0x2000, load_bias);
 
   const std::unordered_map<uint64_t, LoadInfo>& pt_loads = elf->pt_loads();
   ASSERT_EQ(1U, pt_loads.size());
@@ -443,15 +463,15 @@
   ASSERT_EQ(0x10000U, load_data.table_size);
 }
 
-TEST_F(ElfInterfaceTest, elf32_many_phdrs) {
+TEST_F(ElfInterfaceTest, many_phdrs_32) {
   ElfInterfaceTest::ManyPhdrs<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_many_phdrs) {
+TEST_F(ElfInterfaceTest, many_phdrs_64) {
   ElfInterfaceTest::ManyPhdrs<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
 }
 
-TEST_F(ElfInterfaceTest, elf32_arm) {
+TEST_F(ElfInterfaceTest, arm32) {
   ElfInterfaceArm elf_arm(&memory_);
 
   Elf32_Ehdr ehdr = {};
@@ -470,9 +490,9 @@
   memory_.SetData32(0x2000, 0x1000);
   memory_.SetData32(0x2008, 0x1000);
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf_arm.Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 
   std::vector<uint32_t> entries;
   for (auto addr : elf_arm) {
@@ -551,19 +571,19 @@
 void ElfInterfaceTest::Soname() {
   std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 
   ASSERT_EQ("fake_soname.so", elf->GetSoname());
 }
 
-TEST_F(ElfInterfaceTest, elf32_soname) {
+TEST_F(ElfInterfaceTest, soname_32) {
   SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>();
   Soname<ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_soname) {
+TEST_F(ElfInterfaceTest, soname_64) {
   SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>();
   Soname<ElfInterface64>();
 }
@@ -572,19 +592,19 @@
 void ElfInterfaceTest::SonameAfterDtNull() {
   std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 
   ASSERT_EQ("", elf->GetSoname());
 }
 
-TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) {
+TEST_F(ElfInterfaceTest, soname_after_dt_null_32) {
   SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER);
   SonameAfterDtNull<ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) {
+TEST_F(ElfInterfaceTest, soname_after_dt_null_64) {
   SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER);
   SonameAfterDtNull<ElfInterface64>();
 }
@@ -593,19 +613,19 @@
 void ElfInterfaceTest::SonameSize() {
   std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 
   ASSERT_EQ("", elf->GetSoname());
 }
 
-TEST_F(ElfInterfaceTest, elf32_soname_size) {
+TEST_F(ElfInterfaceTest, soname_size_32) {
   SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL);
   SonameSize<ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_soname_size) {
+TEST_F(ElfInterfaceTest, soname_size_64) {
   SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL);
   SonameSize<ElfInterface64>();
 }
@@ -616,19 +636,19 @@
 void ElfInterfaceTest::SonameMissingMap() {
   std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 
   ASSERT_EQ("", elf->GetSoname());
 }
 
-TEST_F(ElfInterfaceTest, elf32_soname_missing_map) {
+TEST_F(ElfInterfaceTest, soname_missing_map_32) {
   SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP);
   SonameMissingMap<ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, elf64_soname_missing_map) {
+TEST_F(ElfInterfaceTest, soname_missing_map_64) {
   SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP);
   SonameMissingMap<ElfInterface64>();
 }
@@ -647,17 +667,17 @@
   memory_.SetData32(0x10004, 0x500);
   memory_.SetData32(0x10008, 250);
 
-  elf.InitHeaders(0);
+  elf.InitHeaders();
 
   EXPECT_FALSE(elf.eh_frame() == nullptr);
   EXPECT_TRUE(elf.debug_frame() == nullptr);
 }
 
-TEST_F(ElfInterfaceTest, init_headers_eh_frame32) {
+TEST_F(ElfInterfaceTest, init_headers_eh_frame_32) {
   InitHeadersEhFrameTest<ElfInterface32Fake>();
 }
 
-TEST_F(ElfInterfaceTest, init_headers_eh_frame64) {
+TEST_F(ElfInterfaceTest, init_headers_eh_frame_64) {
   InitHeadersEhFrameTest<ElfInterface64Fake>();
 }
 
@@ -679,17 +699,17 @@
   memory_.SetData32(0x5108, 0x1500);
   memory_.SetData32(0x510c, 0x200);
 
-  elf.InitHeaders(0);
+  elf.InitHeaders();
 
   EXPECT_TRUE(elf.eh_frame() == nullptr);
   EXPECT_FALSE(elf.debug_frame() == nullptr);
 }
 
-TEST_F(ElfInterfaceTest, init_headers_debug_frame32) {
+TEST_F(ElfInterfaceTest, init_headers_debug_frame_32) {
   InitHeadersDebugFrame<ElfInterface32Fake>();
 }
 
-TEST_F(ElfInterfaceTest, init_headers_debug_frame64) {
+TEST_F(ElfInterfaceTest, init_headers_debug_frame_64) {
   InitHeadersDebugFrame<ElfInterface64Fake>();
 }
 
@@ -703,16 +723,16 @@
   ehdr.e_phentsize = sizeof(Phdr);
   memory_.SetMemory(0, &ehdr, sizeof(ehdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 }
 
-TEST_F(ElfInterfaceTest, init_program_headers_malformed32) {
+TEST_F(ElfInterfaceTest, init_program_headers_malformed_32) {
   InitProgramHeadersMalformed<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, init_program_headers_malformed64) {
+TEST_F(ElfInterfaceTest, init_program_headers_malformed_64) {
   InitProgramHeadersMalformed<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>();
 }
 
@@ -726,16 +746,16 @@
   ehdr.e_shentsize = sizeof(Shdr);
   memory_.SetMemory(0, &ehdr, sizeof(ehdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_malformed32) {
+TEST_F(ElfInterfaceTest, init_section_headers_malformed_32) {
   InitSectionHeadersMalformed<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_malformed64) {
+TEST_F(ElfInterfaceTest, init_section_headers_malformed_64) {
   InitSectionHeadersMalformed<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
 }
 
@@ -790,11 +810,10 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
   EXPECT_EQ(0U, elf->debug_frame_offset());
   EXPECT_EQ(0U, elf->debug_frame_size());
   EXPECT_EQ(0U, elf->gnu_debugdata_offset());
@@ -805,11 +824,11 @@
   ASSERT_FALSE(elf->GetFunctionName(0x90010, &name, &name_offset));
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata32) {
+TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_32) {
   InitSectionHeadersMalformedSymData<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata64) {
+TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_64) {
   InitSectionHeadersMalformedSymData<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
 }
 
@@ -860,14 +879,13 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   InitSym<Sym>(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one");
   InitSym<Sym>(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two");
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
   EXPECT_EQ(0U, elf->debug_frame_offset());
   EXPECT_EQ(0U, elf->debug_frame_size());
   EXPECT_EQ(0U, elf->gnu_debugdata_offset());
@@ -884,19 +902,19 @@
   EXPECT_EQ(32U, name_offset);
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers32) {
+TEST_F(ElfInterfaceTest, init_section_headers_32) {
   InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(sizeof(Elf32_Shdr));
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers64) {
+TEST_F(ElfInterfaceTest, init_section_headers_64) {
   InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(sizeof(Elf64_Shdr));
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size32) {
+TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_32) {
   InitSectionHeaders<Elf32_Ehdr, Elf32_Shdr, Elf32_Sym, ElfInterface32>(0x100);
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size64) {
+TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_64) {
   InitSectionHeaders<Elf64_Ehdr, Elf64_Shdr, Elf64_Sym, ElfInterface64>(0x100);
 }
 
@@ -961,7 +979,7 @@
   shdr.sh_type = SHT_PROGBITS;
   shdr.sh_link = 2;
   shdr.sh_name = 0x400;
-  shdr.sh_addr = 0x6000;
+  shdr.sh_addr = 0xa000;
   shdr.sh_offset = 0xa000;
   shdr.sh_entsize = 0x100;
   shdr.sh_size = 0xf00;
@@ -971,10 +989,10 @@
   memset(&shdr, 0, sizeof(shdr));
   shdr.sh_type = SHT_NOTE;
   shdr.sh_name = 0x500;
+  shdr.sh_addr = 0xb000;
   shdr.sh_offset = 0xb000;
   shdr.sh_size = 0xf00;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
   memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata"));
@@ -982,29 +1000,352 @@
   memory_.SetMemory(0xf400, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
   memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
   EXPECT_EQ(0x6000U, elf->debug_frame_offset());
+  EXPECT_EQ(0, elf->debug_frame_section_bias());
   EXPECT_EQ(0x500U, elf->debug_frame_size());
+
   EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset());
   EXPECT_EQ(0x800U, elf->gnu_debugdata_size());
+
   EXPECT_EQ(0x7000U, elf->eh_frame_offset());
+  EXPECT_EQ(0, elf->eh_frame_section_bias());
   EXPECT_EQ(0x800U, elf->eh_frame_size());
+
   EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset());
+  EXPECT_EQ(0, elf->eh_frame_hdr_section_bias());
   EXPECT_EQ(0xf00U, elf->eh_frame_hdr_size());
+
   EXPECT_EQ(0xb000U, elf->gnu_build_id_offset());
   EXPECT_EQ(0xf00U, elf->gnu_build_id_size());
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_offsets32) {
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_32) {
   InitSectionHeadersOffsets<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, init_section_headers_offsets64) {
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_64) {
   InitSectionHeadersOffsets<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>();
 }
 
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset,
+                                                                   int64_t expected_bias) {
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+  uint64_t elf_offset = 0x2000;
+
+  Ehdr ehdr = {};
+  ehdr.e_shoff = elf_offset;
+  ehdr.e_shnum = 4;
+  ehdr.e_shentsize = sizeof(Shdr);
+  ehdr.e_shstrndx = 2;
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  elf_offset += ehdr.e_shentsize;
+
+  Shdr shdr = {};
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x200;
+  shdr.sh_addr = 0x8000;
+  shdr.sh_offset = 0x8000;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x800;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+  elf_offset += ehdr.e_shentsize;
+
+  // The string data for section header names.
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_STRTAB;
+  shdr.sh_name = 0x20000;
+  shdr.sh_offset = 0xf000;
+  shdr.sh_size = 0x1000;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+  elf_offset += ehdr.e_shentsize;
+
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x100;
+  shdr.sh_addr = addr;
+  shdr.sh_offset = offset;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x500;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+
+  memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame"));
+  memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
+
+  int64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0, load_bias);
+  EXPECT_EQ(offset, elf->eh_frame_offset());
+  EXPECT_EQ(expected_bias, elf->eh_frame_section_bias());
+  EXPECT_EQ(0x500U, elf->eh_frame_size());
+
+  EXPECT_EQ(0x8000U, elf->eh_frame_hdr_offset());
+  EXPECT_EQ(0, elf->eh_frame_hdr_section_bias());
+  EXPECT_EQ(0x800U, elf->eh_frame_hdr_size());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_32) {
+  InitSectionHeadersOffsetsEhFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(0x4000,
+                                                                                      0x4000, 0);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_64) {
+  InitSectionHeadersOffsetsEhFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(0x6000,
+                                                                                      0x6000, 0);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_32) {
+  InitSectionHeadersOffsetsEhFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
+      0x5000, 0x4000, 0x1000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_64) {
+  InitSectionHeadersOffsetsEhFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
+      0x6000, 0x4000, 0x2000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_32) {
+  InitSectionHeadersOffsetsEhFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
+      0x3000, 0x4000, -0x1000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_64) {
+  InitSectionHeadersOffsetsEhFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
+      0x6000, 0x9000, -0x3000);
+}
+
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr,
+                                                                      uint64_t offset,
+                                                                      int64_t expected_bias) {
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+  uint64_t elf_offset = 0x2000;
+
+  Ehdr ehdr = {};
+  ehdr.e_shoff = elf_offset;
+  ehdr.e_shnum = 4;
+  ehdr.e_shentsize = sizeof(Shdr);
+  ehdr.e_shstrndx = 2;
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  elf_offset += ehdr.e_shentsize;
+
+  Shdr shdr = {};
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x200;
+  shdr.sh_addr = addr;
+  shdr.sh_offset = offset;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x800;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+  elf_offset += ehdr.e_shentsize;
+
+  // The string data for section header names.
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_STRTAB;
+  shdr.sh_name = 0x20000;
+  shdr.sh_offset = 0xf000;
+  shdr.sh_size = 0x1000;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+  elf_offset += ehdr.e_shentsize;
+
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x100;
+  shdr.sh_addr = 0x5000;
+  shdr.sh_offset = 0x5000;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x500;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+
+  memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame"));
+  memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr"));
+
+  int64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0, load_bias);
+  EXPECT_EQ(0x5000U, elf->eh_frame_offset());
+  EXPECT_EQ(0, elf->eh_frame_section_bias());
+  EXPECT_EQ(0x500U, elf->eh_frame_size());
+  EXPECT_EQ(offset, elf->eh_frame_hdr_offset());
+  EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias());
+  EXPECT_EQ(0x800U, elf->eh_frame_hdr_size());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_32) {
+  InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(0x9000,
+                                                                                         0x9000, 0);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_64) {
+  InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(0xa000,
+                                                                                         0xa000, 0);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_32) {
+  InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
+      0x9000, 0x4000, 0x5000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_64) {
+  InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
+      0x6000, 0x1000, 0x5000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_32) {
+  InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
+      0x3000, 0x5000, -0x2000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_64) {
+  InitSectionHeadersOffsetsEhFrameHdrSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
+      0x5000, 0x9000, -0x4000);
+}
+
+template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
+void ElfInterfaceTest::InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr,
+                                                                      uint64_t offset,
+                                                                      int64_t expected_bias) {
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+
+  uint64_t elf_offset = 0x2000;
+
+  Ehdr ehdr = {};
+  ehdr.e_shoff = elf_offset;
+  ehdr.e_shnum = 3;
+  ehdr.e_shentsize = sizeof(Shdr);
+  ehdr.e_shstrndx = 2;
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  elf_offset += ehdr.e_shentsize;
+
+  Shdr shdr = {};
+  shdr.sh_type = SHT_PROGBITS;
+  shdr.sh_link = 2;
+  shdr.sh_name = 0x100;
+  shdr.sh_addr = addr;
+  shdr.sh_offset = offset;
+  shdr.sh_entsize = 0x100;
+  shdr.sh_size = 0x800;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+  elf_offset += ehdr.e_shentsize;
+
+  // The string data for section header names.
+  memset(&shdr, 0, sizeof(shdr));
+  shdr.sh_type = SHT_STRTAB;
+  shdr.sh_name = 0x20000;
+  shdr.sh_offset = 0xf000;
+  shdr.sh_size = 0x1000;
+  memory_.SetMemory(elf_offset, &shdr, sizeof(shdr));
+
+  memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame"));
+
+  int64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0, load_bias);
+  EXPECT_EQ(offset, elf->debug_frame_offset());
+  EXPECT_EQ(expected_bias, elf->debug_frame_section_bias());
+  EXPECT_EQ(0x800U, elf->debug_frame_size());
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_32) {
+  InitSectionHeadersOffsetsDebugFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(0x5000,
+                                                                                         0x5000, 0);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_64) {
+  InitSectionHeadersOffsetsDebugFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(0xa000,
+                                                                                         0xa000, 0);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_32) {
+  InitSectionHeadersOffsetsDebugFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
+      0x5000, 0x2000, 0x3000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_64) {
+  InitSectionHeadersOffsetsDebugFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
+      0x7000, 0x1000, 0x6000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_32) {
+  InitSectionHeadersOffsetsDebugFrameSectionBias<Elf32_Ehdr, Elf32_Shdr, ElfInterface32>(
+      0x6000, 0x7000, -0x1000);
+}
+
+TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_64) {
+  InitSectionHeadersOffsetsDebugFrameSectionBias<Elf64_Ehdr, Elf64_Shdr, ElfInterface64>(
+      0x3000, 0x5000, -0x2000);
+}
+
+template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
+void ElfInterfaceTest::CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias) {
+  std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
+
+  Ehdr ehdr = {};
+  ehdr.e_phoff = 0x100;
+  ehdr.e_phnum = 2;
+  ehdr.e_phentsize = sizeof(Phdr);
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  uint64_t phdr_offset = 0x100;
+
+  Phdr phdr = {};
+  phdr.p_type = PT_LOAD;
+  phdr.p_memsz = 0x10000;
+  phdr.p_flags = PF_R | PF_X;
+  phdr.p_align = 0x1000;
+  memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
+  phdr_offset += sizeof(phdr);
+
+  memset(&phdr, 0, sizeof(phdr));
+  phdr.p_type = PT_GNU_EH_FRAME;
+  phdr.p_vaddr = addr;
+  phdr.p_offset = offset;
+  memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr));
+
+  int64_t load_bias = 0;
+  ASSERT_TRUE(elf->Init(&load_bias));
+  EXPECT_EQ(0, load_bias);
+  EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias());
+}
+
+TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_32) {
+  ElfInterfaceTest::CheckGnuEhFrame<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x4000, 0x4000, 0);
+}
+
+TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_64) {
+  ElfInterfaceTest::CheckGnuEhFrame<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x4000, 0x4000, 0);
+}
+
+TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_32) {
+  ElfInterfaceTest::CheckGnuEhFrame<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x4000, 0x1000, 0x3000);
+}
+
+TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_64) {
+  ElfInterfaceTest::CheckGnuEhFrame<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x4000, 0x1000, 0x3000);
+}
+
+TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_32) {
+  ElfInterfaceTest::CheckGnuEhFrame<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x4000, 0x5000,
+                                                                            -0x1000);
+}
+
+TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_64) {
+  ElfInterfaceTest::CheckGnuEhFrame<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x4000, 0x5000,
+                                                                            -0x1000);
+}
+
 TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load) {
   std::unique_ptr<ElfInterface> elf(new ElfInterface32(&memory_));
 
@@ -1022,9 +1363,9 @@
   phdr.p_align = 0x1000;
   memory_.SetMemory(0x100, &phdr, sizeof(phdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0U, load_bias);
+  EXPECT_EQ(0, load_bias);
   EXPECT_TRUE(elf->IsValidPc(0));
   EXPECT_TRUE(elf->IsValidPc(0x5000));
   EXPECT_TRUE(elf->IsValidPc(0xffff));
@@ -1048,9 +1389,9 @@
   phdr.p_align = 0x1000;
   memory_.SetMemory(0x100, &phdr, sizeof(phdr));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  EXPECT_EQ(0x2000U, load_bias);
+  EXPECT_EQ(0x2000, load_bias);
   EXPECT_FALSE(elf->IsValidPc(0));
   EXPECT_FALSE(elf->IsValidPc(0x1000));
   EXPECT_FALSE(elf->IsValidPc(0x1fff));
@@ -1105,10 +1446,10 @@
   memory_.SetData32(0x708, 0x2100);
   memory_.SetData32(0x70c, 0x200);
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  elf->InitHeaders(0);
-  EXPECT_EQ(0U, load_bias);
+  elf->InitHeaders();
+  EXPECT_EQ(0, load_bias);
   EXPECT_FALSE(elf->IsValidPc(0));
   EXPECT_FALSE(elf->IsValidPc(0x20ff));
   EXPECT_TRUE(elf->IsValidPc(0x2100));
@@ -1162,10 +1503,10 @@
   memory_.SetData32(0x708, 0x20f8);
   memory_.SetData32(0x70c, 0x200);
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
-  elf->InitHeaders(0);
-  EXPECT_EQ(0U, load_bias);
+  elf->InitHeaders();
+  EXPECT_EQ(0, load_bias);
   EXPECT_FALSE(elf->IsValidPc(0));
   EXPECT_FALSE(elf->IsValidPc(0x27ff));
   EXPECT_TRUE(elf->IsValidPc(0x2800));
@@ -1201,7 +1542,6 @@
   note_offset += sizeof("GNU");
   // This part of the note does not contain any trailing '\0'.
   memcpy(&note_section[note_offset], "BUILDID", 7);
-  note_offset += 8;
 
   Shdr shdr = {};
   shdr.sh_type = SHT_NOTE;
@@ -1218,16 +1558,23 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
   memory_.SetMemory(0xb000, note_section, sizeof(note_section));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
   ASSERT_EQ("BUILDID", elf->GetBuildID());
 }
 
+TEST_F(ElfInterfaceTest, build_id_32) {
+  BuildID<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, build_id_64) {
+  BuildID<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
+}
+
 template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
 void ElfInterfaceTest::BuildIDTwoNotes() {
   std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
@@ -1266,7 +1613,6 @@
   note_offset += sizeof("GNU");
   // This part of the note does not contain any trailing '\0'.
   memcpy(&note_section[note_offset], "BUILDID", 7);
-  note_offset += 8;
 
   Shdr shdr = {};
   shdr.sh_type = SHT_NOTE;
@@ -1283,16 +1629,23 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
   memory_.SetMemory(0xb000, note_section, sizeof(note_section));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
   ASSERT_EQ("BUILDID", elf->GetBuildID());
 }
 
+TEST_F(ElfInterfaceTest, build_id_two_notes_32) {
+  BuildIDTwoNotes<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, build_id_two_notes_64) {
+  BuildIDTwoNotes<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
+}
+
 template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
 void ElfInterfaceTest::BuildIDSectionTooSmallForName () {
   std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
@@ -1320,7 +1673,6 @@
   note_offset += sizeof("GNU");
   // This part of the note does not contain any trailing '\0'.
   memcpy(&note_section[note_offset], "BUILDID", 7);
-  note_offset += 8;
 
   Shdr shdr = {};
   shdr.sh_type = SHT_NOTE;
@@ -1337,16 +1689,23 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
   memory_.SetMemory(0xb000, note_section, sizeof(note_section));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
   ASSERT_EQ("", elf->GetBuildID());
 }
 
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_32) {
+  BuildIDSectionTooSmallForName<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_64) {
+  BuildIDSectionTooSmallForName<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
+}
+
 template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
 void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () {
   std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
@@ -1374,7 +1733,6 @@
   note_offset += sizeof("GNU");
   // This part of the note does not contain any trailing '\0'.
   memcpy(&note_section[note_offset], "BUILDID", 7);
-  note_offset += 8;
 
   Shdr shdr = {};
   shdr.sh_type = SHT_NOTE;
@@ -1391,16 +1749,23 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
   memory_.SetMemory(0xb000, note_section, sizeof(note_section));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
   ASSERT_EQ("", elf->GetBuildID());
 }
 
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_32) {
+  BuildIDSectionTooSmallForDesc<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_64) {
+  BuildIDSectionTooSmallForDesc<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
+}
+
 template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
 void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () {
   std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
@@ -1428,7 +1793,6 @@
   note_offset += sizeof("GNU");
   // This part of the note does not contain any trailing '\0'.
   memcpy(&note_section[note_offset], "BUILDID", 7);
-  note_offset += 8;
 
   Shdr shdr = {};
   shdr.sh_type = SHT_NOTE;
@@ -1445,54 +1809,158 @@
   shdr.sh_offset = 0xf000;
   shdr.sh_size = 0x1000;
   memory_.SetMemory(offset, &shdr, sizeof(shdr));
-  offset += ehdr.e_shentsize;
 
   memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id"));
   memory_.SetMemory(0xb000, note_section, sizeof(note_section));
 
-  uint64_t load_bias = 0;
+  int64_t load_bias = 0;
   ASSERT_TRUE(elf->Init(&load_bias));
   ASSERT_EQ("", elf->GetBuildID());
 }
 
-TEST_F(ElfInterfaceTest, build_id32) {
-  BuildID<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id64) {
-  BuildID<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_two_notes32) {
-  BuildIDTwoNotes<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_two_notes64) {
-  BuildIDTwoNotes<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name32) {
-  BuildIDSectionTooSmallForName<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name64) {
-  BuildIDSectionTooSmallForName<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc32) {
-  BuildIDSectionTooSmallForDesc<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc64) {
-  BuildIDSectionTooSmallForDesc<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
-}
-
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header32) {
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_32) {
   BuildIDSectionTooSmallForHeader<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr, ElfInterface32>();
 }
 
-TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header64) {
+TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_64) {
   BuildIDSectionTooSmallForHeader<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr, ElfInterface64>();
 }
 
+template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
+void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(int64_t load_bias) {
+  Ehdr ehdr = {};
+  ehdr.e_phoff = 0x100;
+  ehdr.e_phnum = 2;
+  ehdr.e_phentsize = sizeof(Phdr);
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  Phdr phdr = {};
+  phdr.p_type = PT_LOAD;
+  phdr.p_offset = 0;
+  phdr.p_vaddr = load_bias;
+  phdr.p_memsz = 0x10000;
+  phdr.p_flags = PF_R | PF_X;
+  phdr.p_align = 0x1000;
+  memory_.SetMemory(0x100, &phdr, sizeof(phdr));
+
+  memset(&phdr, 0, sizeof(phdr));
+  phdr.p_type = PT_LOAD;
+  phdr.p_offset = 0x1000;
+  phdr.p_memsz = 0x2000;
+  phdr.p_flags = PF_R | PF_X;
+  phdr.p_align = 0x1000;
+  memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
+
+  int64_t static_load_bias = ElfInterface::GetLoadBias<Ehdr, Phdr>(&memory_);
+  ASSERT_EQ(load_bias, static_load_bias);
+
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+  int64_t init_load_bias = 0;
+  ASSERT_TRUE(elf->Init(&init_load_bias));
+  ASSERT_EQ(init_load_bias, static_load_bias);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_zero_32) {
+  CheckLoadBiasInFirstPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_zero_64) {
+  CheckLoadBiasInFirstPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_non_zero_32) {
+  CheckLoadBiasInFirstPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_non_zero_64) {
+  CheckLoadBiasInFirstPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000);
+}
+
+template <typename Ehdr, typename Phdr, typename ElfInterfaceType>
+void ElfInterfaceTest::CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr,
+                                                    int64_t load_bias) {
+  Ehdr ehdr = {};
+  ehdr.e_phoff = 0x100;
+  ehdr.e_phnum = 3;
+  ehdr.e_phentsize = sizeof(Phdr);
+  memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+
+  Phdr phdr = {};
+  phdr.p_type = PT_LOAD;
+  phdr.p_memsz = 0x10000;
+  phdr.p_flags = PF_R;
+  phdr.p_align = 0x1000;
+  memory_.SetMemory(0x100, &phdr, sizeof(phdr));
+
+  memset(&phdr, 0, sizeof(phdr));
+  phdr.p_type = PT_LOAD;
+  phdr.p_offset = offset;
+  phdr.p_vaddr = vaddr;
+  phdr.p_memsz = 0x2000;
+  phdr.p_flags = PF_R | PF_X;
+  phdr.p_align = 0x1000;
+  memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr));
+
+  // Second executable load should be ignored for load bias computation.
+  memset(&phdr, 0, sizeof(phdr));
+  phdr.p_type = PT_LOAD;
+  phdr.p_offset = 0x1234;
+  phdr.p_vaddr = 0x2000;
+  phdr.p_memsz = 0x2000;
+  phdr.p_flags = PF_R | PF_X;
+  phdr.p_align = 0x1000;
+  memory_.SetMemory(0x200 + sizeof(phdr), &phdr, sizeof(phdr));
+
+  int64_t static_load_bias = ElfInterface::GetLoadBias<Ehdr, Phdr>(&memory_);
+  ASSERT_EQ(load_bias, static_load_bias);
+
+  std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
+  int64_t init_load_bias = 0;
+  ASSERT_TRUE(elf->Init(&init_load_bias));
+  ASSERT_EQ(init_load_bias, static_load_bias);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_32) {
+  CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000, 0x1000, 0);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_64) {
+  CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000, 0x1000, 0);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_32) {
+  CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x1000, 0x4000, 0x3000);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_64) {
+  CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x1000, 0x4000, 0x3000);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_32) {
+  CheckLoadBiasInFirstExecPhdr<Elf32_Ehdr, Elf32_Phdr, ElfInterface32>(0x5000, 0x1000, -0x4000);
+}
+
+TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_64) {
+  CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x5000, 0x1000, -0x4000);
+}
+
+TEST_F(ElfInterfaceTest, huge_gnu_debugdata_size) {
+  ElfInterfaceFake interface(nullptr);
+
+  interface.FakeSetGnuDebugdataOffset(0x1000);
+  interface.FakeSetGnuDebugdataSize(0xffffffffffffffffUL);
+  ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
+
+  interface.FakeSetGnuDebugdataSize(0x4000000000000UL);
+  ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
+
+  // This should exceed the size_t value of the first allocation.
+#if defined(__LP64__)
+  interface.FakeSetGnuDebugdataSize(0x3333333333333334ULL);
+#else
+  interface.FakeSetGnuDebugdataSize(0x33333334);
+#endif
+  ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index c432d6d..4866345 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -104,6 +104,8 @@
     memory_->SetMemory(0x100, &phdr, sizeof(phdr));
   }
 
+  void VerifyStepIfSignalHandler(uint64_t load_bias);
+
   MemoryFake* memory_;
 };
 
@@ -281,7 +283,7 @@
   ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
 }
 
-TEST_F(ElfTest, step_in_signal_map) {
+void ElfTest::VerifyStepIfSignalHandler(uint64_t load_bias) {
   ElfFake elf(memory_);
 
   RegsArm regs;
@@ -290,6 +292,7 @@
 
   ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
   elf.FakeSetInterface(interface);
+  elf.FakeSetLoadBias(load_bias);
 
   memory_->SetData32(0x3000, 0xdf0027ad);
   MemoryFake process_memory;
@@ -299,30 +302,42 @@
   }
 
   elf.FakeSetValid(true);
-  ASSERT_TRUE(elf.StepIfSignalHandler(0x3000, &regs, &process_memory));
+  ASSERT_TRUE(elf.StepIfSignalHandler(0x3000 + load_bias, &regs, &process_memory));
   EXPECT_EQ(ERROR_NONE, elf.GetLastErrorCode());
   EXPECT_EQ(15U, regs.pc());
   EXPECT_EQ(13U, regs.sp());
 }
 
+TEST_F(ElfTest, step_in_signal_map) {
+  VerifyStepIfSignalHandler(0);
+}
+
+TEST_F(ElfTest, step_in_signal_map_non_zero_load_bias) {
+  VerifyStepIfSignalHandler(0x1000);
+}
+
 class ElfInterfaceMock : public ElfInterface {
  public:
   ElfInterfaceMock(Memory* memory) : ElfInterface(memory) {}
   virtual ~ElfInterfaceMock() = default;
 
-  bool Init(uint64_t*) override { return false; }
-  void InitHeaders(uint64_t) override {}
+  bool Init(int64_t*) override { return false; }
+  void InitHeaders() override {}
   std::string GetSoname() override { return ""; }
   bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
   std::string GetBuildID() override { return ""; }
 
-  MOCK_METHOD4(Step, bool(uint64_t, Regs*, Memory*, bool*));
-  MOCK_METHOD2(GetGlobalVariable, bool(const std::string&, uint64_t*));
-  MOCK_METHOD1(IsValidPc, bool(uint64_t));
+  MOCK_METHOD(bool, Step, (uint64_t, Regs*, Memory*, bool*), (override));
+  MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override));
+  MOCK_METHOD(bool, IsValidPc, (uint64_t), (override));
+
+  void MockSetDataOffset(uint64_t offset) { data_offset_ = offset; }
+  void MockSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; }
+  void MockSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; }
 
   void MockSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; }
-  void MockSetDynamicVaddr(uint64_t vaddr) { dynamic_vaddr_ = vaddr; }
-  void MockSetDynamicSize(uint64_t size) { dynamic_size_ = size; }
+  void MockSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
+  void MockSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
 };
 
 TEST_F(ElfTest, step_in_interface) {
@@ -348,7 +363,7 @@
 
   std::string global("something");
   uint64_t offset;
-  ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
+  ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
 }
 
 TEST_F(ElfTest, get_global_valid_not_in_interface) {
@@ -358,119 +373,69 @@
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
 
-  uint64_t offset;
   std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)).WillOnce(::testing::Return(false));
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
+      .WillOnce(::testing::Return(false));
 
-  ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
+  uint64_t offset;
+  ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
 }
 
-TEST_F(ElfTest, get_global_valid_below_load_bias) {
+TEST_F(ElfTest, get_global_vaddr_in_no_sections) {
   ElfFake elf(memory_);
   elf.FakeSetValid(true);
-  elf.FakeSetLoadBias(0x1000);
 
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
 
-  uint64_t offset;
   std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
       .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
 
-  ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
-}
-
-TEST_F(ElfTest, get_global_valid_dynamic_zero_non_zero_load_bias) {
-  ElfFake elf(memory_);
-  elf.FakeSetValid(true);
-  elf.FakeSetLoadBias(0x100);
-
-  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
-  elf.FakeSetInterface(interface);
-
   uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x200U, offset);
+  ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset));
 }
 
-TEST_F(ElfTest, get_global_valid_dynamic_zero) {
+TEST_F(ElfTest, get_global_vaddr_in_data_section) {
   ElfFake elf(memory_);
   elf.FakeSetValid(true);
 
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
+  interface->MockSetDataVaddrStart(0x500);
+  interface->MockSetDataVaddrEnd(0x600);
+  interface->MockSetDataOffset(0xa000);
 
-  ElfInterfaceMock* gnu_interface = new ElfInterfaceMock(memory_);
-  elf.FakeSetGnuDebugdataInterface(gnu_interface);
+  std::string global("something");
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
+      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x580), ::testing::Return(true)));
 
   uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)).WillOnce(::testing::Return(false));
-
-  EXPECT_CALL(*gnu_interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x500), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x500U, offset);
+  ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
+  EXPECT_EQ(0xa080U, offset);
 }
 
-TEST_F(ElfTest, get_global_valid_in_gnu_debugdata_dynamic_zero) {
+TEST_F(ElfTest, get_global_vaddr_in_dynamic_section) {
   ElfFake elf(memory_);
   elf.FakeSetValid(true);
 
   ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
   elf.FakeSetInterface(interface);
+  interface->MockSetDataVaddrStart(0x500);
+  interface->MockSetDataVaddrEnd(0x600);
+  interface->MockSetDataOffset(0xa000);
+
+  interface->MockSetDynamicVaddrStart(0x800);
+  interface->MockSetDynamicVaddrEnd(0x900);
+  interface->MockSetDynamicOffset(0xc000);
+
+  std::string global("something");
+  EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_))
+      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x880), ::testing::Return(true)));
 
   uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x300U, offset);
-}
-
-TEST_F(ElfTest, get_global_valid_dynamic_adjust_negative) {
-  ElfFake elf(memory_);
-  elf.FakeSetValid(true);
-
-  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
-  interface->MockSetDynamicOffset(0x400);
-  interface->MockSetDynamicVaddr(0x800);
-  interface->MockSetDynamicSize(0x100);
-  elf.FakeSetInterface(interface);
-
-  uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x850), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x450U, offset);
-}
-
-TEST_F(ElfTest, get_global_valid_dynamic_adjust_positive) {
-  ElfFake elf(memory_);
-  elf.FakeSetValid(true);
-
-  ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
-  interface->MockSetDynamicOffset(0x1000);
-  interface->MockSetDynamicVaddr(0x800);
-  interface->MockSetDynamicSize(0x100);
-  elf.FakeSetInterface(interface);
-
-  uint64_t offset;
-  std::string global("something");
-  EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
-      .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x850), ::testing::Return(true)));
-
-  ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
-  EXPECT_EQ(0x1050U, offset);
+  ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset));
+  EXPECT_EQ(0xc080U, offset);
 }
 
 TEST_F(ElfTest, is_valid_pc_elf_invalid) {
diff --git a/libmemunreachable/tests/HostMallocStub.cpp b/libunwindstack/tests/IsolatedSettings.cpp
similarity index 66%
copy from libmemunreachable/tests/HostMallocStub.cpp
copy to libunwindstack/tests/IsolatedSettings.cpp
index 0ef0487..dbd8bd6 100644
--- a/libmemunreachable/tests/HostMallocStub.cpp
+++ b/libunwindstack/tests/IsolatedSettings.cpp
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
-#include "bionic.h"
+#include <stdint.h>
+#include <stdio.h>
 
-void malloc_disable() {}
-
-void malloc_enable() {}
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+  static const char* initial_args[2] = {"--slow_threshold_ms=90000",
+                                        "--deadline_threshold_ms=120000"};
+  *args = initial_args;
+  *num_args = 2;
+  return true;
+}
diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp
index b1ca111..9b32a3a 100644
--- a/libunwindstack/tests/JitDebugTest.cpp
+++ b/libunwindstack/tests/JitDebugTest.cpp
@@ -35,13 +35,17 @@
 
 class JitDebugTest : public ::testing::Test {
  protected:
-  void CreateFakeElf(MapInfo* map_info) {
+  void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset,
+                     uint64_t data_vaddr, uint64_t data_size) {
     MemoryFake* memory = new MemoryFake;
     ElfFake* elf = new ElfFake(memory);
     elf->FakeSetValid(true);
     ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
     elf->FakeSetInterface(interface);
-    interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
+    interface->FakeSetGlobalVariable("__jit_debug_descriptor", global_offset);
+    interface->FakeSetDataOffset(data_offset);
+    interface->FakeSetDataVaddrStart(data_vaddr);
+    interface->FakeSetDataVaddrEnd(data_vaddr + data_size);
     map_info->elf.reset(elf);
   }
 
@@ -52,27 +56,27 @@
     maps_.reset(
         new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n"
                        "4000-6000 r--s 00000000 00:00 0 /fake/elf1\n"
-                       "6000-8000 -wxs 00000000 00:00 0 /fake/elf1\n"
+                       "6000-8000 -wxs 00002000 00:00 0 /fake/elf1\n"
                        "a000-c000 --xp 00000000 00:00 0 /fake/elf2\n"
-                       "c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
+                       "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n"
                        "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
-                       "11000-12000 rw-p 00001000 00:00 0 /fake/elf3\n"
+                       "11000-12000 rw-p 00002000 00:00 0 /fake/elf3\n"
                        "12000-14000 r--p 00000000 00:00 0 /fake/elf4\n"
-                       "100000-110000 rw-p 0001000 00:00 0 /fake/elf4\n"
-                       "200000-210000 rw-p 0002000 00:00 0 /fake/elf4\n"));
+                       "100000-110000 rw-p 00ee000 00:00 0 /fake/elf4\n"
+                       "200000-210000 rw-p 01ee000 00:00 0 /fake/elf4\n"));
     ASSERT_TRUE(maps_->Parse());
 
     MapInfo* map_info = maps_->Get(3);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     map_info = maps_->Get(5);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000);
 
     map_info = maps_->Get(7);
     ASSERT_TRUE(map_info != nullptr);
-    CreateFakeElf(map_info);
+    CreateFakeElf(map_info, 0xee800, 0xee000, 0xee000, 0x10000);
   }
 
   void SetUp() override {
@@ -258,7 +262,7 @@
 TEST_F(JitDebugTest, get_elf_no_valid_code_entry) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
@@ -267,7 +271,7 @@
 TEST_F(JitDebugTest, get_elf_invalid_descriptor_first_entry) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0);
+  WriteDescriptor32(0x11800, 0);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
@@ -276,9 +280,9 @@
 TEST_F(JitDebugTest, get_elf_invalid_descriptor_version) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x20000);
+  WriteDescriptor32(0x11800, 0x20000);
   // Set the version to an invalid value.
-  memory_->SetData32(0xf800, 2);
+  memory_->SetData32(0x11800, 2);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
   ASSERT_TRUE(elf == nullptr);
@@ -287,7 +291,7 @@
 TEST_F(JitDebugTest, get_elf_32) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
@@ -304,16 +308,16 @@
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2000, 0x300);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
-  WriteDescriptor32(0x12800, 0x201000);
+  WriteDescriptor32(0x100800, 0x201000);
   WriteEntry32Pad(0x201000, 0, 0, 0x5000, 0x1000);
 
   ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr);
   ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) == nullptr);
 
   // Now clear the descriptor entry for the first one.
-  WriteDescriptor32(0xf800, 0);
+  WriteDescriptor32(0x11800, 0);
   jit_debug_.reset(new JitDebug(process_memory_));
   jit_debug_->SetArch(ARCH_ARM);
 
@@ -326,7 +330,7 @@
 
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pack(0x200000, 0, 0, 0x4000, 0x1000);
 
   jit_debug_->SetArch(ARCH_X86);
@@ -345,7 +349,7 @@
 
   CreateElf<Elf64_Ehdr, Elf64_Shdr>(0x4000, ELFCLASS64, EM_AARCH64, 0x1500, 0x200);
 
-  WriteDescriptor64(0xf800, 0x200000);
+  WriteDescriptor64(0x11800, 0x200000);
   WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000);
 
   Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500);
@@ -362,7 +366,7 @@
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x5000, ELFCLASS32, EM_ARM, 0x2300, 0x400);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0x200100, 0x4000, 0x1000);
   WriteEntry32Pad(0x200100, 0x200100, 0, 0x5000, 0x1000);
 
@@ -385,7 +389,7 @@
 TEST_F(JitDebugTest, get_elf_search_libs) {
   CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200);
 
-  WriteDescriptor32(0xf800, 0x200000);
+  WriteDescriptor32(0x11800, 0x200000);
   WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000);
 
   // Only search a given named list of libs.
diff --git a/libunwindstack/tests/LocalUnwinderTest.cpp b/libunwindstack/tests/LocalUnwinderTest.cpp
index 56a18cd..9936f7a 100644
--- a/libunwindstack/tests/LocalUnwinderTest.cpp
+++ b/libunwindstack/tests/LocalUnwinderTest.cpp
@@ -170,10 +170,10 @@
 
   std::string testlib(testing::internal::GetArgvs()[0]);
   auto const value = testlib.find_last_of('/');
-  if (value == std::string::npos) {
-    testlib = "../";
+  if (value != std::string::npos) {
+    testlib = testlib.substr(0, value + 1);
   } else {
-    testlib = testlib.substr(0, value + 1) + "../";
+    testlib = "";
   }
   testlib += "libunwindstack_local.so";
 
diff --git a/libunwindstack/tests/LocalUpdatableMapsTest.cpp b/libunwindstack/tests/LocalUpdatableMapsTest.cpp
new file mode 100644
index 0000000..b816b9a
--- /dev/null
+++ b/libunwindstack/tests/LocalUpdatableMapsTest.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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 <stdint.h>
+#include <sys/mman.h>
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <android-base/file.h>
+#include <unwindstack/Maps.h>
+
+namespace unwindstack {
+
+class TestUpdatableMaps : public LocalUpdatableMaps {
+ public:
+  TestUpdatableMaps() : LocalUpdatableMaps() {}
+  virtual ~TestUpdatableMaps() = default;
+
+  const std::string GetMapsFile() const override { return maps_file_; }
+
+  void TestSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; }
+
+  const std::vector<std::unique_ptr<MapInfo>>& TestGetSavedMaps() { return saved_maps_; }
+
+ private:
+  std::string maps_file_;
+};
+
+class LocalUpdatableMapsTest : public ::testing::Test {
+ protected:
+  static const std::string GetDefaultMapString() {
+    return "3000-4000 r-xp 00000 00:00 0\n8000-9000 r-xp 00000 00:00 0\n";
+  }
+
+  void SetUp() override {
+    TemporaryFile tf;
+    ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path));
+
+    maps_.TestSetMapsFile(tf.path);
+    ASSERT_TRUE(maps_.Parse());
+    ASSERT_EQ(2U, maps_.Total());
+
+    MapInfo* map_info = maps_.Get(0);
+    ASSERT_TRUE(map_info != nullptr);
+    EXPECT_EQ(0x3000U, map_info->start);
+    EXPECT_EQ(0x4000U, map_info->end);
+    EXPECT_EQ(0U, map_info->offset);
+    EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+    EXPECT_TRUE(map_info->name.empty());
+
+    map_info = maps_.Get(1);
+    ASSERT_TRUE(map_info != nullptr);
+    EXPECT_EQ(0x8000U, map_info->start);
+    EXPECT_EQ(0x9000U, map_info->end);
+    EXPECT_EQ(0U, map_info->offset);
+    EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+    EXPECT_TRUE(map_info->name.empty());
+  }
+
+  TestUpdatableMaps maps_;
+};
+
+TEST_F(LocalUpdatableMapsTest, same_map) {
+  TemporaryFile tf;
+  ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path));
+
+  maps_.TestSetMapsFile(tf.path);
+  ASSERT_TRUE(maps_.Reparse());
+  ASSERT_EQ(2U, maps_.Total());
+  EXPECT_EQ(0U, maps_.TestGetSavedMaps().size());
+
+  MapInfo* map_info = maps_.Get(0);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = maps_.Get(1);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x8000U, map_info->start);
+  EXPECT_EQ(0x9000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+}
+
+TEST_F(LocalUpdatableMapsTest, same_map_new_perms) {
+  TemporaryFile tf;
+  ASSERT_TRUE(
+      android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n"
+                                       "8000-9000 r-xp 00000 00:00 0\n",
+                                       tf.path));
+
+  maps_.TestSetMapsFile(tf.path);
+  ASSERT_TRUE(maps_.Reparse());
+  ASSERT_EQ(2U, maps_.Total());
+
+  MapInfo* map_info = maps_.Get(0);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = maps_.Get(1);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x8000U, map_info->start);
+  EXPECT_EQ(0x9000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  auto& saved_maps = maps_.TestGetSavedMaps();
+  ASSERT_EQ(1U, saved_maps.size());
+  map_info = saved_maps[0].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+}
+
+TEST_F(LocalUpdatableMapsTest, same_map_new_name) {
+  TemporaryFile tf;
+  ASSERT_TRUE(
+      android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
+                                       "8000-9000 r-xp 00000 00:00 0\n",
+                                       tf.path));
+
+  maps_.TestSetMapsFile(tf.path);
+  ASSERT_TRUE(maps_.Reparse());
+  ASSERT_EQ(2U, maps_.Total());
+
+  MapInfo* map_info = maps_.Get(0);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_EQ("/fake/lib.so", map_info->name);
+
+  map_info = maps_.Get(1);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x8000U, map_info->start);
+  EXPECT_EQ(0x9000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  auto& saved_maps = maps_.TestGetSavedMaps();
+  ASSERT_EQ(1U, saved_maps.size());
+  map_info = saved_maps[0].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+}
+
+TEST_F(LocalUpdatableMapsTest, only_add_maps) {
+  TemporaryFile tf;
+  ASSERT_TRUE(
+      android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n"
+                                       "3000-4000 r-xp 00000 00:00 0\n"
+                                       "8000-9000 r-xp 00000 00:00 0\n"
+                                       "a000-f000 r-xp 00000 00:00 0\n",
+                                       tf.path));
+
+  maps_.TestSetMapsFile(tf.path);
+  ASSERT_TRUE(maps_.Reparse());
+  ASSERT_EQ(4U, maps_.Total());
+  EXPECT_EQ(0U, maps_.TestGetSavedMaps().size());
+
+  MapInfo* map_info = maps_.Get(0);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x1000U, map_info->start);
+  EXPECT_EQ(0x2000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = maps_.Get(1);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = maps_.Get(2);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x8000U, map_info->start);
+  EXPECT_EQ(0x9000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = maps_.Get(3);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0xa000U, map_info->start);
+  EXPECT_EQ(0xf000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+}
+
+TEST_F(LocalUpdatableMapsTest, all_new_maps) {
+  TemporaryFile tf;
+  ASSERT_TRUE(
+      android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n"
+                                       "a000-f000 r-xp 00000 00:00 0\n",
+                                       tf.path));
+
+  maps_.TestSetMapsFile(tf.path);
+  ASSERT_TRUE(maps_.Reparse());
+  ASSERT_EQ(2U, maps_.Total());
+
+  MapInfo* map_info = maps_.Get(0);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x1000U, map_info->start);
+  EXPECT_EQ(0x2000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = maps_.Get(1);
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0xa000U, map_info->start);
+  EXPECT_EQ(0xf000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  auto& saved_maps = maps_.TestGetSavedMaps();
+  ASSERT_EQ(2U, saved_maps.size());
+  map_info = saved_maps[0].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x3000U, map_info->start);
+  EXPECT_EQ(0x4000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+
+  map_info = saved_maps[1].get();
+  ASSERT_TRUE(map_info != nullptr);
+  EXPECT_EQ(0x8000U, map_info->start);
+  EXPECT_EQ(0x9000U, map_info->end);
+  EXPECT_EQ(0U, map_info->offset);
+  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
+  EXPECT_TRUE(map_info->name.empty());
+}
+
+}  // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 6be8bdc..6c1cfa2 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -58,7 +58,7 @@
     ASSERT_TRUE(android::base::WriteFully(fd, buffer.data(), buffer.size()));
   }
 
-  static void SetUpTestCase() {
+  void SetUp() override {
     std::vector<uint8_t> buffer(12288, 0);
     memcpy(buffer.data(), ELFMAG, SELFMAG);
     buffer[EI_CLASS] = ELFCLASS32;
@@ -72,9 +72,7 @@
 
     InitElf<Elf32_Ehdr, Elf32_Shdr>(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32);
     InitElf<Elf64_Ehdr, Elf64_Shdr>(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64);
-  }
 
-  void SetUp() override {
     memory_ = new MemoryFake;
     process_memory_.reset(memory_);
   }
@@ -82,17 +80,13 @@
   MemoryFake* memory_;
   std::shared_ptr<Memory> process_memory_;
 
-  static TemporaryFile elf_;
+  TemporaryFile elf_;
 
-  static TemporaryFile elf_at_1000_;
+  TemporaryFile elf_at_1000_;
 
-  static TemporaryFile elf32_at_map_;
-  static TemporaryFile elf64_at_map_;
+  TemporaryFile elf32_at_map_;
+  TemporaryFile elf64_at_map_;
 };
-TemporaryFile MapInfoCreateMemoryTest::elf_;
-TemporaryFile MapInfoCreateMemoryTest::elf_at_1000_;
-TemporaryFile MapInfoCreateMemoryTest::elf32_at_map_;
-TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_;
 
 TEST_F(MapInfoCreateMemoryTest, end_le_start) {
   MapInfo info(nullptr, 0x100, 0x100, 0, 0, elf_.path);
diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
index f5ac6cb..da3dbf2 100644
--- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
+++ b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp
@@ -84,7 +84,7 @@
   elf_->FakeSetLoadBias(0);
   EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_));
 
-  map_info_->load_bias = static_cast<uint64_t>(-1);
+  map_info_->load_bias = INT64_MAX;
   elf_->FakeSetLoadBias(0x1000);
   EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_));
 }
@@ -141,6 +141,7 @@
   phdr.p_type = PT_NULL;
   memory->SetMemory(offset + 0x5000, &phdr, sizeof(phdr));
   phdr.p_type = PT_LOAD;
+  phdr.p_flags = PF_X;
   phdr.p_offset = 0;
   phdr.p_vaddr = 0xe000;
   memory->SetMemory(offset + 0x5000 + sizeof(phdr), &phdr, sizeof(phdr));
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp
index e2cbb98..ef76b1b 100644
--- a/libunwindstack/tests/MapInfoTest.cpp
+++ b/libunwindstack/tests/MapInfoTest.cpp
@@ -35,7 +35,7 @@
   EXPECT_EQ(3UL, map_info.offset);
   EXPECT_EQ(4UL, map_info.flags);
   EXPECT_EQ("map", map_info.name);
-  EXPECT_EQ(static_cast<uint64_t>(-1), map_info.load_bias);
+  EXPECT_EQ(INT64_MAX, map_info.load_bias);
   EXPECT_EQ(0UL, map_info.elf_offset);
   EXPECT_TRUE(map_info.elf.get() == nullptr);
 }
@@ -51,7 +51,7 @@
   EXPECT_EQ(3UL, map_info.offset);
   EXPECT_EQ(4UL, map_info.flags);
   EXPECT_EQ("string_map", map_info.name);
-  EXPECT_EQ(static_cast<uint64_t>(-1), map_info.load_bias);
+  EXPECT_EQ(INT64_MAX, map_info.load_bias);
   EXPECT_EQ(0UL, map_info.elf_offset);
   EXPECT_TRUE(map_info.elf.get() == nullptr);
 }
diff --git a/libunwindstack/tests/MemoryBufferTest.cpp b/libunwindstack/tests/MemoryBufferTest.cpp
index 28e0e76..a6c12aa 100644
--- a/libunwindstack/tests/MemoryBufferTest.cpp
+++ b/libunwindstack/tests/MemoryBufferTest.cpp
@@ -18,9 +18,8 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
-
 #include "LogFake.h"
+#include "MemoryBuffer.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryCacheTest.cpp b/libunwindstack/tests/MemoryCacheTest.cpp
index a3def20..3bd3e4d 100644
--- a/libunwindstack/tests/MemoryCacheTest.cpp
+++ b/libunwindstack/tests/MemoryCacheTest.cpp
@@ -20,8 +20,7 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
-
+#include "MemoryCache.h"
 #include "MemoryFake.h"
 
 namespace unwindstack {
diff --git a/libunwindstack/tests/MemoryFileTest.cpp b/libunwindstack/tests/MemoryFileTest.cpp
index d7d1ace..4124a49 100644
--- a/libunwindstack/tests/MemoryFileTest.cpp
+++ b/libunwindstack/tests/MemoryFileTest.cpp
@@ -21,7 +21,7 @@
 #include <android-base/file.h>
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
+#include "MemoryFileAtOffset.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryLocalTest.cpp b/libunwindstack/tests/MemoryLocalTest.cpp
index 5a389d0..c9e5dc0 100644
--- a/libunwindstack/tests/MemoryLocalTest.cpp
+++ b/libunwindstack/tests/MemoryLocalTest.cpp
@@ -22,7 +22,7 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
+#include "MemoryLocal.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryOfflineBufferTest.cpp b/libunwindstack/tests/MemoryOfflineBufferTest.cpp
index f022884..9531708 100644
--- a/libunwindstack/tests/MemoryOfflineBufferTest.cpp
+++ b/libunwindstack/tests/MemoryOfflineBufferTest.cpp
@@ -18,9 +18,8 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
-
 #include "LogFake.h"
+#include "MemoryOfflineBuffer.h"
 
 namespace unwindstack {
 
@@ -31,7 +30,7 @@
     memory_.reset(new MemoryOfflineBuffer(buffer_.data(), kStart, kEnd));
   }
 
-  static void SetUpTestCase() {
+  static void SetUpTestSuite() {
     buffer_.resize(kLength);
     for (size_t i = 0; i < kLength; i++) {
       buffer_[i] = i % 189;
diff --git a/libunwindstack/tests/MemoryOfflineTest.cpp b/libunwindstack/tests/MemoryOfflineTest.cpp
index ab9aa9d..d0c441b 100644
--- a/libunwindstack/tests/MemoryOfflineTest.cpp
+++ b/libunwindstack/tests/MemoryOfflineTest.cpp
@@ -19,7 +19,8 @@
 #include <gtest/gtest.h>
 
 #include <android-base/file.h>
-#include <unwindstack/Memory.h>
+
+#include "MemoryOffline.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
index 2bac95b..2d4f141 100644
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ b/libunwindstack/tests/MemoryRangeTest.cpp
@@ -21,9 +21,8 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
-
 #include "MemoryFake.h"
+#include "MemoryRange.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp
index d24fcd2..e4e9fc4 100644
--- a/libunwindstack/tests/MemoryRangesTest.cpp
+++ b/libunwindstack/tests/MemoryRangesTest.cpp
@@ -20,9 +20,8 @@
 
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
-
 #include "MemoryFake.h"
+#include "MemoryRange.h"
 
 namespace unwindstack {
 
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
index fb56e8a..c90dedc 100644
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ b/libunwindstack/tests/MemoryRemoteTest.cpp
@@ -30,7 +30,7 @@
 #include <android-base/file.h>
 #include <gtest/gtest.h>
 
-#include <unwindstack/Memory.h>
+#include "MemoryRemote.h"
 
 #include "MemoryFake.h"
 #include "TestUtils.h"
diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp
index 9a27dbd..bc95851 100644
--- a/libunwindstack/tests/RegsIterateTest.cpp
+++ b/libunwindstack/tests/RegsIterateTest.cpp
@@ -114,6 +114,7 @@
   result.push_back({"sp", ARM64_REG_SP});
   result.push_back({"lr", ARM64_REG_LR});
   result.push_back({"pc", ARM64_REG_PC});
+  result.push_back({"pst", ARM64_REG_PSTATE});
   return result;
 }
 
@@ -236,7 +237,7 @@
 }
 
 using RegTypes = ::testing::Types<RegsArm, RegsArm64, RegsX86, RegsX86_64, RegsMips, RegsMips64>;
-TYPED_TEST_CASE(RegsIterateTest, RegTypes);
+TYPED_TEST_SUITE(RegsIterateTest, RegTypes);
 
 TYPED_TEST(RegsIterateTest, iterate) {
   std::vector<Register> expected = ExpectedRegisters<TypeParam>();
diff --git a/libunwindstack/tests/SymbolsTest.cpp b/libunwindstack/tests/SymbolsTest.cpp
index b40a253..c58aeff 100644
--- a/libunwindstack/tests/SymbolsTest.cpp
+++ b/libunwindstack/tests/SymbolsTest.cpp
@@ -55,7 +55,7 @@
 
   MemoryFake memory_;
 };
-TYPED_TEST_CASE_P(SymbolsTest);
+TYPED_TEST_SUITE_P(SymbolsTest);
 
 TYPED_TEST_P(SymbolsTest, function_bounds_check) {
   Symbols symbols(0x1000, sizeof(TypeParam), sizeof(TypeParam), 0x2000, 0x100);
@@ -362,11 +362,11 @@
   EXPECT_EQ(4U, offset);
 }
 
-REGISTER_TYPED_TEST_CASE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries,
-                           multiple_entries_nonstandard_size, symtab_value_out_of_bounds,
-                           symtab_read_cached, get_global);
+REGISTER_TYPED_TEST_SUITE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries,
+                            multiple_entries_nonstandard_size, symtab_value_out_of_bounds,
+                            symtab_read_cached, get_global);
 
 typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes;
-INSTANTIATE_TYPED_TEST_CASE_P(, SymbolsTest, SymbolsTestTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, SymbolsTest, SymbolsTestTypes);
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 6c64c40..364101a 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -35,7 +35,6 @@
 #include <unwindstack/MachineX86.h>
 #include <unwindstack/MachineX86_64.h>
 #include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
 #include <unwindstack/RegsArm.h>
 #include <unwindstack/RegsArm64.h>
 #include <unwindstack/RegsX86.h>
@@ -43,6 +42,7 @@
 #include <unwindstack/Unwinder.h>
 
 #include "ElfTestUtils.h"
+#include "MemoryOffline.h"
 #include "TestUtils.h"
 
 namespace unwindstack {
@@ -62,7 +62,7 @@
     free(cwd_);
   }
 
-  void Init(const char* file_dir, ArchEnum arch) {
+  void Init(const char* file_dir, ArchEnum arch, bool add_stack = true) {
     dir_ = TestGetFileDirectory() + "offline/" + file_dir;
 
     std::string data;
@@ -71,23 +71,25 @@
     maps_.reset(new BufferMaps(data.c_str()));
     ASSERT_TRUE(maps_->Parse());
 
-    std::string stack_name(dir_ + "stack.data");
-    struct stat st;
-    if (stat(stack_name.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
-      std::unique_ptr<MemoryOffline> stack_memory(new MemoryOffline);
-      ASSERT_TRUE(stack_memory->Init((dir_ + "stack.data").c_str(), 0));
-      process_memory_.reset(stack_memory.release());
-    } else {
-      std::unique_ptr<MemoryOfflineParts> stack_memory(new MemoryOfflineParts);
-      for (size_t i = 0;; i++) {
-        stack_name = dir_ + "stack" + std::to_string(i) + ".data";
-        if (stat(stack_name.c_str(), &st) == -1 || !S_ISREG(st.st_mode)) {
-          ASSERT_TRUE(i != 0) << "No stack data files found.";
-          break;
+    if (add_stack) {
+      std::string stack_name(dir_ + "stack.data");
+      struct stat st;
+      if (stat(stack_name.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
+        std::unique_ptr<MemoryOffline> stack_memory(new MemoryOffline);
+        ASSERT_TRUE(stack_memory->Init((dir_ + "stack.data").c_str(), 0));
+        process_memory_.reset(stack_memory.release());
+      } else {
+        std::unique_ptr<MemoryOfflineParts> stack_memory(new MemoryOfflineParts);
+        for (size_t i = 0;; i++) {
+          stack_name = dir_ + "stack" + std::to_string(i) + ".data";
+          if (stat(stack_name.c_str(), &st) == -1 || !S_ISREG(st.st_mode)) {
+            ASSERT_TRUE(i != 0) << "No stack data files found.";
+            break;
+          }
+          AddMemory(stack_name, stack_memory.get());
         }
-        AddMemory(stack_name, stack_memory.get());
+        process_memory_.reset(stack_memory.release());
       }
-      process_memory_.reset(stack_memory.release());
     }
 
     switch (arch) {
@@ -1442,4 +1444,257 @@
   EXPECT_EQ(0x7be4f07d20ULL, unwinder.frames()[12].sp);
 }
 
+TEST_F(UnwindOfflineTest, invalid_elf_offset_arm) {
+  ASSERT_NO_FATAL_FAILURE(Init("invalid_elf_offset_arm/", ARCH_ARM, false));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(1U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ("  #00 pc 00aa7508  invalid.apk (offset 0x12e4000)\n", frame_info);
+  EXPECT_EQ(0xc898f508, unwinder.frames()[0].pc);
+  EXPECT_EQ(0xc2044218, unwinder.frames()[0].sp);
+}
+
+TEST_F(UnwindOfflineTest, load_bias_ro_rx_x86_64) {
+  ASSERT_NO_FATAL_FAILURE(Init("load_bias_ro_rx_x86_64/", ARCH_X86_64));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000e9dd4  libc.so (__write+20)\n"
+      "  #01 pc 000000000007ab9c  libc.so (_IO_file_write+44)\n"
+      "  #02 pc 0000000000079f3e  libc.so\n"
+      "  #03 pc 000000000007bce8  libc.so (_IO_do_write+24)\n"
+      "  #04 pc 000000000007b26e  libc.so (_IO_file_xsputn+270)\n"
+      "  #05 pc 000000000004f7f9  libc.so (_IO_vfprintf+1945)\n"
+      "  #06 pc 0000000000057cb5  libc.so (_IO_printf+165)\n"
+      "  #07 pc 0000000000ed1796  perfetto_unittests "
+      "(testing::internal::PrettyUnitTestResultPrinter::OnTestIterationStart(testing::UnitTest "
+      "const&, int)+374)\n"
+      "  #08 pc 0000000000ed30fd  perfetto_unittests "
+      "(testing::internal::TestEventRepeater::OnTestIterationStart(testing::UnitTest const&, "
+      "int)+125)\n"
+      "  #09 pc 0000000000ed5e25  perfetto_unittests "
+      "(testing::internal::UnitTestImpl::RunAllTests()+581)\n"
+      "  #10 pc 0000000000ef63f3  perfetto_unittests "
+      "(bool "
+      "testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, "
+      "bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char "
+      "const*)+131)\n"
+      "  #11 pc 0000000000ee2a21  perfetto_unittests "
+      "(bool "
+      "testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, "
+      "bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char "
+      "const*)+113)\n"
+      "  #12 pc 0000000000ed5bb9  perfetto_unittests (testing::UnitTest::Run()+185)\n"
+      "  #13 pc 0000000000e900f0  perfetto_unittests (RUN_ALL_TESTS()+16)\n"
+      "  #14 pc 0000000000e900d8  perfetto_unittests (main+56)\n"
+      "  #15 pc 000000000002352a  libc.so (__libc_start_main+234)\n"
+      "  #16 pc 0000000000919029  perfetto_unittests (_start+41)\n",
+      frame_info);
+
+  EXPECT_EQ(0x7f9326a57dd4ULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0x7ffd224153c8ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0x7f93269e8b9cULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0x7ffd224153d0ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0x7f93269e7f3eULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0x7ffd22415400ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0x7f93269e9ce8ULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0x7ffd22415440ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0x7f93269e926eULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0x7ffd22415450ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0x7f93269bd7f9ULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0x7ffd22415490ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0x7f93269c5cb5ULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0x7ffd22415a10ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0xed1796ULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0x7ffd22415af0ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0xed30fdULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0x7ffd22415b70ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0xed5e25ULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0x7ffd22415bb0ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0xef63f3ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0x7ffd22415c60ULL, unwinder.frames()[10].sp);
+  EXPECT_EQ(0xee2a21ULL, unwinder.frames()[11].pc);
+  EXPECT_EQ(0x7ffd22415cc0ULL, unwinder.frames()[11].sp);
+  EXPECT_EQ(0xed5bb9ULL, unwinder.frames()[12].pc);
+  EXPECT_EQ(0x7ffd22415d40ULL, unwinder.frames()[12].sp);
+  EXPECT_EQ(0xe900f0ULL, unwinder.frames()[13].pc);
+  EXPECT_EQ(0x7ffd22415d90ULL, unwinder.frames()[13].sp);
+  EXPECT_EQ(0xe900d8ULL, unwinder.frames()[14].pc);
+  EXPECT_EQ(0x7ffd22415da0ULL, unwinder.frames()[14].sp);
+  EXPECT_EQ(0x7f932699152aULL, unwinder.frames()[15].pc);
+  EXPECT_EQ(0x7ffd22415dd0ULL, unwinder.frames()[15].sp);
+  EXPECT_EQ(0x919029ULL, unwinder.frames()[16].pc);
+  EXPECT_EQ(0x7ffd22415e90ULL, unwinder.frames()[16].sp);
+}
+
+TEST_F(UnwindOfflineTest, load_bias_different_section_bias_arm64) {
+  ASSERT_NO_FATAL_FAILURE(Init("load_bias_different_section_bias_arm64/", ARCH_ARM64));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(12U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000d59bc  linker64 (__dl_syscall+28)\n"
+      "  #01 pc 00000000000554e8  linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1148)\n"
+      "  #02 pc 00000000000008c0  vdso (__kernel_rt_sigreturn)\n"
+      "  #03 pc 000000000007f3e8  libc.so (abort+168)\n"
+      "  #04 pc 00000000000459fc  test (std::__ndk1::__throw_bad_cast()+4)\n"
+      "  #05 pc 0000000000056d80  test (testing::Test::Run()+88)\n"
+      "  #06 pc 000000000005724c  test (testing::TestInfo::Run()+112)\n"
+      "  #07 pc 0000000000057558  test (testing::TestSuite::Run()+116)\n"
+      "  #08 pc 000000000005bffc  test (testing::internal::UnitTestImpl::RunAllTests()+464)\n"
+      "  #09 pc 000000000005bd9c  test (testing::UnitTest::Run()+116)\n"
+      "  #10 pc 00000000000464e4  test (main+144)\n"
+      "  #11 pc 000000000007aa34  libc.so (__libc_init+108)\n",
+      frame_info);
+
+  EXPECT_EQ(0x7112cb99bcULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0x7112c394e8ULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0x7112be28c0ULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0x7112bdbda0ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0x71115ab3e8ULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0x7fdd4a3f00ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0x5f739dc9fcULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0x7fdd4a3fe0ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0x5f739edd80ULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0x7fdd4a3ff0ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0x5f739ee24cULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0x7fdd4a4010ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0x5f739ee558ULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0x7fdd4a4040ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0x5f739f2ffcULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0x7fdd4a4070ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0x5f739f2d9cULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0x7fdd4a4100ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0x5f739dd4e4ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0x7fdd4a4130ULL, unwinder.frames()[10].sp);
+  EXPECT_EQ(0x71115a6a34ULL, unwinder.frames()[11].pc);
+  EXPECT_EQ(0x7fdd4a4170ULL, unwinder.frames()[11].sp);
+}
+
+TEST_F(UnwindOfflineTest, eh_frame_bias_x86) {
+  ASSERT_NO_FATAL_FAILURE(Init("eh_frame_bias_x86/", ARCH_X86));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(11U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc ffffe430  vdso.so (__kernel_vsyscall+16)\n"
+      "  #01 pc 00082a4b  libc.so (__epoll_pwait+43)\n"
+      "  #02 pc 000303a3  libc.so (epoll_pwait+115)\n"
+      "  #03 pc 000303ed  libc.so (epoll_wait+45)\n"
+      "  #04 pc 00010ea2  tombstoned (epoll_dispatch+226)\n"
+      "  #05 pc 0000c5e7  tombstoned (event_base_loop+1095)\n"
+      "  #06 pc 0000c193  tombstoned (event_base_dispatch+35)\n"
+      "  #07 pc 00005c77  tombstoned (main+884)\n"
+      "  #08 pc 00015f66  libc.so (__libc_init+102)\n"
+      "  #09 pc 0000360e  tombstoned (_start+98)\n"
+      "  #10 pc 00000001  <unknown>\n",
+      frame_info);
+
+  EXPECT_EQ(0xffffe430ULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0xfffe1a30ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0xeb585a4bULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0xfffe1a40ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0xeb5333a3ULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0xfffe1a60ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0xeb5333edULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0xfffe1ab0ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0xeb841ea2ULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0xfffe1ae0ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0xeb83d5e7ULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0xfffe1b30ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0xeb83d193ULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0xfffe1bd0ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0xeb836c77ULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0xfffe1c00ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0xeb518f66ULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0xfffe1d00ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0xeb83460eULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0xfffe1d40ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0x00000001ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0xfffe1d74ULL, unwinder.frames()[10].sp);
+}
+
+TEST_F(UnwindOfflineTest, signal_load_bias_arm) {
+  ASSERT_NO_FATAL_FAILURE(Init("signal_load_bias_arm/", ARCH_ARM));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 0029ef9e  libunwindstack_unit_test (SignalInnerFunction+10)\n"
+      "  #01 pc 0029efa7  libunwindstack_unit_test (SignalMiddleFunction+2)\n"
+      "  #02 pc 0029efaf  libunwindstack_unit_test (SignalOuterFunction+2)\n"
+      "  #03 pc 002a280b  libunwindstack_unit_test (unwindstack::SignalCallerHandler(int, "
+      "siginfo*, void*)+10)\n"
+      "  #04 pc 00058bd4  libc.so (__restore)\n"
+      "  #05 pc 0029f01e  libunwindstack_unit_test (InnerFunction+106)\n"
+      "  #06 pc 0029f633  libunwindstack_unit_test (MiddleFunction+16)\n"
+      "  #07 pc 0029f64b  libunwindstack_unit_test (OuterFunction+16)\n"
+      "  #08 pc 002a1711  libunwindstack_unit_test (unwindstack::RemoteThroughSignal(int, unsigned "
+      "int)+260)\n"
+      "  #09 pc 002a1603  libunwindstack_unit_test "
+      "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+10)\n"
+      "  #10 pc 002c8fe3  libunwindstack_unit_test (testing::Test::Run()+130)\n"
+      "  #11 pc 002c9b25  libunwindstack_unit_test (testing::TestInfo::Run()+184)\n"
+      "  #12 pc 002c9e27  libunwindstack_unit_test (testing::TestSuite::Run()+202)\n"
+      "  #13 pc 002d193d  libunwindstack_unit_test "
+      "(testing::internal::UnitTestImpl::RunAllTests()+660)\n"
+      "  #14 pc 002d160b  libunwindstack_unit_test (testing::UnitTest::Run()+134)\n"
+      "  #15 pc 002de035  libunwindstack_unit_test (IsolateMain+680)\n"
+      "  #16 pc 00058155  libc.so (__libc_init+68)\n",
+      frame_info);
+
+  EXPECT_EQ(0xb6955f9eULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0xb6955fa7ULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0xb6955fafULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0xf2790cf0ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0xb695980bULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0xf2790cf8ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0xf23febd4ULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0xf2790d10ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0xb695601eULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0xffe67798ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0xb6956633ULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0xffe67890ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0xb695664bULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0xffe678a0ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0xb6958711ULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0xffe678b0ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0xb6958603ULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0xffe67ac8ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0xb697ffe3ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0xffe67ad8ULL, unwinder.frames()[10].sp);
+  EXPECT_EQ(0xb6980b25ULL, unwinder.frames()[11].pc);
+  EXPECT_EQ(0xffe67ae8ULL, unwinder.frames()[11].sp);
+  EXPECT_EQ(0xb6980e27ULL, unwinder.frames()[12].pc);
+  EXPECT_EQ(0xffe67b18ULL, unwinder.frames()[12].sp);
+  EXPECT_EQ(0xb698893dULL, unwinder.frames()[13].pc);
+  EXPECT_EQ(0xffe67b48ULL, unwinder.frames()[13].sp);
+  EXPECT_EQ(0xb698860bULL, unwinder.frames()[14].pc);
+  EXPECT_EQ(0xffe67bb0ULL, unwinder.frames()[14].sp);
+  EXPECT_EQ(0xb6995035ULL, unwinder.frames()[15].pc);
+  EXPECT_EQ(0xffe67bd0ULL, unwinder.frames()[15].sp);
+  EXPECT_EQ(0xf23fe155ULL, unwinder.frames()[16].pc);
+  EXPECT_EQ(0xffe67d10ULL, unwinder.frames()[16].sp);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 4e38015..f76a101 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -35,11 +35,11 @@
 #include <android-base/threads.h>
 
 #include <unwindstack/Maps.h>
-#include <unwindstack/Memory.h>
 #include <unwindstack/Regs.h>
 #include <unwindstack/RegsGetLocal.h>
 #include <unwindstack/Unwinder.h>
 
+#include "MemoryRemote.h"
 #include "TestUtils.h"
 
 namespace unwindstack {
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 30e57a1..ef1950c 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -54,7 +54,7 @@
     }
   }
 
-  static void SetUpTestCase() {
+  static void SetUpTestSuite() {
     maps_.reset(new Maps);
 
     ElfFake* elf = new ElfFake(new MemoryFake);
@@ -132,6 +132,10 @@
     const auto& info6 = *--maps_->end();
     info6->memory_backed_elf = true;
 
+    AddMapInfo(0xd0000, 0xd1000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.apk");
+    const auto& info7 = *--maps_->end();
+    info7->load_bias = 0;
+
     process_memory_.reset(new MemoryFake);
   }
 
@@ -1015,6 +1019,50 @@
   EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
 }
 
+TEST_F(UnwinderTest, dex_pc_in_map_non_zero_offset) {
+  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+  regs_.set_pc(0x1000);
+  regs_.set_sp(0x10000);
+  regs_.FakeSetDexPc(0xd0400);
+
+  Unwinder unwinder(64, maps_.get(), &regs_, process_memory_);
+  unwinder.Unwind();
+  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
+
+  ASSERT_EQ(2U, unwinder.NumFrames());
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0x400U, frame->rel_pc);
+  EXPECT_EQ(0xd0400U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/fake/fake.apk", frame->map_name);
+  EXPECT_EQ(0x1000U, frame->map_elf_start_offset);
+  EXPECT_EQ(0x1000U, frame->map_exact_offset);
+  EXPECT_EQ(0xd0000U, frame->map_start);
+  EXPECT_EQ(0xd1000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+
+  frame = &unwinder.frames()[1];
+  EXPECT_EQ(1U, frame->num);
+  EXPECT_EQ(0U, frame->rel_pc);
+  EXPECT_EQ(0x1000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("Frame0", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  EXPECT_EQ("/system/fake/libc.so", frame->map_name);
+  EXPECT_EQ(0U, frame->map_elf_start_offset);
+  EXPECT_EQ(0U, frame->map_exact_offset);
+  EXPECT_EQ(0x1000U, frame->map_start);
+  EXPECT_EQ(0x8000U, frame->map_end);
+  EXPECT_EQ(0U, frame->map_load_bias);
+  EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
+}
+
 TEST_F(UnwinderTest, dex_pc_not_in_map) {
   ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
   regs_.set_pc(0x1000);
diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
new file mode 100644
index 0000000..6a3e91a
--- /dev/null
+++ b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#define _GNU_SOURCE 1
+#include <stdint.h>
+#include <string.h>
+
+#include <string>
+
+#if defined(__BIONIC__)
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/DwarfSection.h>
+#include <unwindstack/Elf.h>
+#include <unwindstack/ElfInterface.h>
+#include <unwindstack/Regs.h>
+#include <unwindstack/RegsGetLocal.h>
+#include <unwindstack/Unwinder.h>
+
+// This test is specific to bionic to verify that __libc_init is
+// properly setting the return address to undefined so that the
+// unwind properly terminates.
+
+namespace unwindstack {
+
+static std::string DumpFrames(const UnwinderFromPid& unwinder) {
+  std::string unwind;
+  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
+    unwind += unwinder.FormatFrame(i) + '\n';
+  }
+  return unwind;
+}
+
+static DwarfLocationEnum GetReturnAddressLocation(uint64_t rel_pc, DwarfSection* section) {
+  if (section == nullptr) {
+    return DWARF_LOCATION_INVALID;
+  }
+
+  const DwarfFde* fde = section->GetFdeFromPc(rel_pc);
+  if (fde == nullptr || fde->cie == nullptr) {
+    return DWARF_LOCATION_INVALID;
+  }
+  dwarf_loc_regs_t regs;
+  if (!section->GetCfaLocationInfo(rel_pc, fde, &regs)) {
+    return DWARF_LOCATION_INVALID;
+  }
+
+  auto reg_entry = regs.find(fde->cie->return_address_register);
+  if (reg_entry == regs.end()) {
+    return DWARF_LOCATION_INVALID;
+  }
+  return reg_entry->second.type;
+}
+
+static void VerifyReturnAddress(const FrameData& frame) {
+  // Now go and find information about the register data and verify that the relative pc results in
+  // an undefined register.
+  Elf elf(Memory::CreateFileMemory(frame.map_name, 0).release());
+  ASSERT_TRUE(elf.Init()) << "Failed to init elf object from " << frame.map_name;
+  ASSERT_TRUE(elf.valid()) << "Elf " << frame.map_name << " is not valid.";
+  ElfInterface* interface = elf.interface();
+
+  // Only check the eh_frame and the debug_frame since the undefined register
+  // is set using a cfi directive.
+  // Check debug_frame first, then eh_frame since debug_frame always
+  // contains the most specific data.
+  DwarfLocationEnum location = GetReturnAddressLocation(frame.rel_pc, interface->debug_frame());
+  if (location == DWARF_LOCATION_UNDEFINED) {
+    return;
+  }
+
+  location = GetReturnAddressLocation(frame.rel_pc, interface->eh_frame());
+  ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location);
+}
+
+// This test assumes that it starts from the main thread, and that the
+// libc.so on device will include symbols so that function names can
+// be resolved.
+TEST(VerifyBionicTermination, local_terminate) {
+  std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
+
+  UnwinderFromPid unwinder(512, getpid());
+  ASSERT_TRUE(unwinder.Init(regs->Arch()));
+  unwinder.SetRegs(regs.get());
+
+  RegsGetLocal(regs.get());
+  unwinder.Unwind();
+  ASSERT_LT(0U, unwinder.NumFrames());
+
+  SCOPED_TRACE(DumpFrames(unwinder));
+
+  // Look for the frame that includes __libc_init, there should only
+  // be one and it should be the last.
+  bool found = false;
+  const std::vector<FrameData>& frames = unwinder.frames();
+  for (size_t i = 0; i < unwinder.NumFrames(); i++) {
+    const FrameData& frame = frames[i];
+    if (frame.function_name == "__libc_init" && !frame.map_name.empty() &&
+        std::string("libc.so") == basename(frame.map_name.c_str())) {
+      ASSERT_EQ(unwinder.NumFrames(), i + 1) << "__libc_init is not last frame.";
+      ASSERT_NO_FATAL_FAILURE(VerifyReturnAddress(frame));
+      found = true;
+    }
+  }
+  ASSERT_TRUE(found) << "Unable to find libc.so:__libc_init frame\n";
+}
+
+}  // namespace unwindstack
+
+#endif
diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
index 5657373..1ff12db 100644
--- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
@@ -1,4 +1,4 @@
 d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
 e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
-e4ae8000-e4ae9000 rw-p 1000 00:00 0 libart.so
+e4af1000-e4af2000 rw-p 482000 00:00 0 libart.so
 e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
new file mode 100644
index 0000000..f3eb615
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
new file mode 100644
index 0000000..7d52483
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt
@@ -0,0 +1,3 @@
+eb503000-eb5e8000 r-xp 0 00:00 0   libc.so
+eb831000-eb852000 r-xp 0 00:00 0   tombstoned
+ffffe000-fffff000 r-xp 0 00:00 0   vdso.so
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
new file mode 100644
index 0000000..821928e
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt
@@ -0,0 +1,9 @@
+eax: fffffffc
+ebx: 4
+ecx: eb290180
+edx: 20
+ebp: 8
+edi: 0
+esi: ffffffff
+esp: fffe1a30
+eip: ffffe430
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
new file mode 100644
index 0000000..b95bfac
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
new file mode 100644
index 0000000..aefdb6b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned
Binary files differ
diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
new file mode 100644
index 0000000..c71dcfb
--- /dev/null
+++ b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt
new file mode 100644
index 0000000..022404c
--- /dev/null
+++ b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt
@@ -0,0 +1 @@
+c7ee8000-c8c52fff r-xp  12e4000    00:00 0  invalid.apk
diff --git a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt
new file mode 100644
index 0000000..b7f10ef
--- /dev/null
+++ b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt
@@ -0,0 +1,16 @@
+r0: c0434c00
+r1: 2a4c9fbc
+r2: 00000000
+r3: c83ef1f9
+r4: 00000004
+r5: c2044904
+r6: 00000000
+r7: c20443b8
+r8: 000b33ff
+r9: c20444b0
+r10: cac90740
+r11: 00000000
+ip: ed891ca4
+sp: c2044218
+lr: ed807265
+pc: c898f508
diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
index 4043122..3b87f2f 100644
--- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt
@@ -4,8 +4,8 @@
 e0447000-e0448000 r-xp 2000 00:00 0   137-cfi.odex
 e2796000-e4796000 r-xp 0 00:00 0   anonymous:e2796000
 e648e000-e690f000 r-xp 0 00:00 0  libart.so
-e690f000-e6910000 rw-p 1000 00:00 0  libart.so
+e6918000-e6919000 rw-p 489000 00:00 0  libart.so
 ed306000-ed801000 r-xp 0 00:00 0   libartd.so
-ed801000-ed802000 rw-p 1000 00:00 0   libartd.so
+ed80a000-ed80b000 rw-p 503000 00:00 0   libartd.so
 eda88000-edb23000 r-xp 0 00:00 0   libc.so
 ede4e000-ede50000 r-xp 0 00:00 0   anonymous:ede4e000
diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
index f255a44..c22b5de 100644
--- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
+++ b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt
@@ -4,5 +4,5 @@
 ec606000-ec607000 r-xp 2000 00:00 0   137-cfi.odex
 ee74c000-f074c000 r-xp 0 00:00 0   anonymous:ee74c000
 f6be1000-f732b000 r-xp 0 00:00 0   libartd.so
-f732b000-f732c000 rw-p 1000 00:00 0   libartd.so
+f7334000-f7335000 rw-p 752000 00:00 0   libartd.so
 f734b000-f74fc000 r-xp 0 00:00 0   libc.so
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so
new file mode 100644
index 0000000..7bb7156
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64
new file mode 100644
index 0000000..00a3896
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt
new file mode 100644
index 0000000..a2babee
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt
@@ -0,0 +1,7 @@
+5f73997000-5f739dc000 r--p 0 00:00 0   test
+5f739dc000-5f73a43000 r-xp 44000 00:00 0   test
+711152c000-711156e000 r--p 0 00:00 0   libc.so
+711156e000-7111611000 --xp 42000 00:00 0   libc.so
+7112be2000-7112be4000 r-xp 0 00:00 0   vdso
+7112be4000-7112c1c000 r--p 0 00:00 0   linker64
+7112c1c000-7112ce1000 r-xp 38000 00:00 0   linker64
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt
new file mode 100644
index 0000000..3c601e1
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt
@@ -0,0 +1,33 @@
+x0: 7112bdbc24
+x1: 0
+x2: ffffffff
+x3: 0
+x4: 0
+x5: 0
+x6: 0
+x7: 7f7f7f7f7f7f7f7f
+x8: 62
+x9: a78826643b37f4a1
+x10: 7112bdbc20
+x11: 4100
+x12: 7112bdbb70
+x13: 18
+x14: 1d6518077
+x15: 2a43148faf732a
+x16: 16fc0
+x17: 71115f61a0
+x18: 7111d6a000
+x19: 7112cef1b0
+x20: 7112bdbda0
+x21: 59616d61
+x22: 1
+x23: 7112bdbc24
+x24: 4b0e
+x25: 62
+x26: 2
+x27: 0
+x28: 7111934020
+x29: 7112bdbd90
+sp: 7112bdbbf0
+lr: 7112c394ec
+pc: 7112cb99bc
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data
new file mode 100644
index 0000000..1674733
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data
new file mode 100644
index 0000000..6d7b48a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test
new file mode 100644
index 0000000..3a75b8f
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso
new file mode 100644
index 0000000..4940916
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
new file mode 100644
index 0000000..63383d0
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
new file mode 100644
index 0000000..ba5a31b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt
@@ -0,0 +1,3 @@
+200000-919000 r--p 0 00:00 0   perfetto_unittests
+919000-1a0c000 r-xp 719000 00:00 0   perfetto_unittests
+7f932696e000-7f9326b23000 r-xp 0 00:00 0   libc.so
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
new file mode 100644
index 0000000..a30e599
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests
Binary files differ
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
new file mode 100644
index 0000000..6cb4055
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt
@@ -0,0 +1,17 @@
+rax: 3b
+rbx: 3b
+rcx: 7f9326a57dd4
+rdx: 3b
+r8: 7ffd22415b09
+r9: 7ffd224155e0
+r10: 0
+r11: 246
+r12: 7f9326d28760
+r13: 3b
+r14: 7f9326d23760
+r15: 3b
+rdi: 1
+rsi: 2678850
+rbp: 2678850
+rsp: 7ffd224153c8
+rip: 7f9326a57dd4
diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
new file mode 100644
index 0000000..4edfe07
--- /dev/null
+++ b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so
new file mode 100644
index 0000000..f046624
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test b/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test
new file mode 100644
index 0000000..f460dd6
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt
new file mode 100644
index 0000000..165ae49
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt
@@ -0,0 +1,4 @@
+b66b7000-b670c000 r--p 0 00:00 0   libunwindstack_unit_test
+b670c000-b69a8000 r-xp 54000 00:00 0   libunwindstack_unit_test
+f23a6000-f23d0000 r--p 0 00:00 0   libc.so
+f23d0000-f2451000 r-xp 29000 00:00 0   libc.so
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt
new file mode 100644
index 0000000..e03f8fd
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt
@@ -0,0 +1,16 @@
+r0: b69b7c84
+r1: 1
+r2: 1
+r3: 1
+r4: f1e52bd0
+r5: f1e11000
+r6: f1e52bd0
+r7: f1e52a38
+r8: f1e11000
+r9: 5de82a8f
+r10: f1e06030
+r11: f1e6d080
+ip: ffe67a88
+sp: f2790ce8
+lr: b6955fab
+pc: b6955f9e
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data
new file mode 100644
index 0000000..d9f23f8
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data
new file mode 100644
index 0000000..6011883
--- /dev/null
+++ b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data
Binary files differ
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 4f67d67..64b58a8 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -275,6 +275,9 @@
 
     if (maps_by_start.count(frame.map_start) == 0) {
       map_info = maps->Find(frame.map_start);
+      if (map_info == nullptr) {
+        continue;
+      }
 
       auto info = FillInAndGetMapInfo(maps_by_start, map_info);
       bool file_copied = false;
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 92e5c0a..7a6d8ba 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -31,6 +31,7 @@
 #include <unwindstack/Elf.h>
 #include <unwindstack/ElfInterface.h>
 #include <unwindstack/Log.h>
+#include <unwindstack/Memory.h>
 
 #include "ArmExidx.h"
 #include "ElfInterfaceArm.h"
@@ -105,14 +106,7 @@
   // Send all log messages to stdout.
   log_to_stdout(true);
 
-  MemoryFileAtOffset* memory = new MemoryFileAtOffset;
-  if (!memory->Init(file, offset)) {
-    // Initializatation failed.
-    printf("Failed to init\n");
-    return 1;
-  }
-
-  Elf elf(memory);
+  Elf elf(Memory::CreateFileMemory(file, offset).release());
   if (!elf.Init() || !elf.valid()) {
     printf("%s is not a valid elf file.\n", file);
     return 1;
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index b77a86b..0cbcac5 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -33,6 +33,7 @@
 #include <unwindstack/Elf.h>
 #include <unwindstack/ElfInterface.h>
 #include <unwindstack/Log.h>
+#include <unwindstack/Memory.h>
 
 #include "ArmExidx.h"
 #include "DwarfOp.h"
@@ -164,15 +165,8 @@
   }
 }
 
-int GetInfo(const char* file, uint64_t pc) {
-  MemoryFileAtOffset* memory = new MemoryFileAtOffset;
-  if (!memory->Init(file, 0)) {
-    // Initializatation failed.
-    printf("Failed to init\n");
-    return 1;
-  }
-
-  Elf elf(memory);
+int GetInfo(const char* file, uint64_t offset, uint64_t pc) {
+  Elf elf(Memory::CreateFileMemory(file, offset).release());
   if (!elf.Init() || !elf.valid()) {
     printf("%s is not a valid elf file.\n", file);
     return 1;
@@ -205,7 +199,7 @@
   DwarfSection* section = interface->eh_frame();
   if (section != nullptr) {
     printf("\neh_frame:\n");
-    PrintRegInformation(section, memory, pc, elf.class_type());
+    PrintRegInformation(section, elf.memory(), pc, elf.class_type());
   } else {
     printf("\nno eh_frame information\n");
   }
@@ -213,7 +207,7 @@
   section = interface->debug_frame();
   if (section != nullptr) {
     printf("\ndebug_frame:\n");
-    PrintRegInformation(section, memory, pc, elf.class_type());
+    PrintRegInformation(section, elf.memory(), pc, elf.class_type());
     printf("\n");
   } else {
     printf("\nno debug_frame information\n");
@@ -249,12 +243,14 @@
 }  // namespace unwindstack
 
 int main(int argc, char** argv) {
-  if (argc != 3) {
-    printf("Usage: unwind_reg_info ELF_FILE PC\n");
+  if (argc != 3 && argc != 4) {
+    printf("Usage: unwind_reg_info ELF_FILE PC [OFFSET]\n");
     printf("  ELF_FILE\n");
     printf("    The path to an elf file.\n");
     printf("  PC\n");
     printf("    The pc for which the register information should be obtained.\n");
+    printf("  OFFSET\n");
+    printf("    Use the offset into the ELF file as the beginning of the elf.\n");
     return 1;
   }
 
@@ -276,5 +272,15 @@
     return 1;
   }
 
-  return unwindstack::GetInfo(argv[1], pc);
+  uint64_t offset = 0;
+  if (argc == 4) {
+    char* end;
+    offset = strtoull(argv[3], &end, 16);
+    if (*end != '\0') {
+      printf("Malformed OFFSET value: %s\n", argv[3]);
+      return 1;
+    }
+  }
+
+  return unwindstack::GetInfo(argv[1], offset, pc);
 }
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index b0a4dd0..8df2284 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -59,13 +59,7 @@
   // Send all log messages to stdout.
   unwindstack::log_to_stdout(true);
 
-  unwindstack::MemoryFileAtOffset* memory = new unwindstack::MemoryFileAtOffset;
-  if (!memory->Init(argv[1], 0)) {
-    printf("Failed to init\n");
-    return 1;
-  }
-
-  unwindstack::Elf elf(memory);
+  unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(argv[1], 0).release());
   if (!elf.Init() || !elf.valid()) {
     printf("%s is not a valid elf file.\n", argv[1]);
     return 1;
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 4f194c7..efa4c41 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -17,6 +17,7 @@
     vendor_available: true,
     recovery_available: true,
     host_supported: true,
+    native_bridge_supported: true,
 
     header_libs: [
         "liblog_headers",
@@ -121,8 +122,10 @@
 cc_library {
     name: "libutils",
     defaults: ["libutils_defaults"],
+    native_bridge_supported: true,
 
     srcs: [
+        "Errors.cpp",
         "FileMap.cpp",
         "JenkinsHash.cpp",
         "NativeHandle.cpp",
@@ -203,6 +206,7 @@
         "Mutex_test.cpp",
         "SharedBuffer_test.cpp",
         "String8_test.cpp",
+        "String16_test.cpp",
         "StrongPointer_test.cpp",
         "Unicode_test.cpp",
         "Vector_test.cpp",
@@ -287,3 +291,9 @@
     ],
     shared_libs: ["libutils_test_singleton1"],
 }
+
+cc_benchmark {
+    name: "libutils_benchmark",
+    srcs: ["Vector_benchmark.cpp"],
+    shared_libs: ["libutils"],
+}
diff --git a/libutils/Errors.cpp b/libutils/Errors.cpp
new file mode 100644
index 0000000..74f3bef
--- /dev/null
+++ b/libutils/Errors.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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 <utils/Errors.h>
+
+namespace android {
+
+std::string statusToString(status_t s) {
+#define STATUS_CASE(STATUS) \
+    case STATUS:            \
+        return #STATUS
+
+    switch (s) {
+        STATUS_CASE(OK);
+        STATUS_CASE(UNKNOWN_ERROR);
+        STATUS_CASE(NO_MEMORY);
+        STATUS_CASE(INVALID_OPERATION);
+        STATUS_CASE(BAD_VALUE);
+        STATUS_CASE(BAD_TYPE);
+        STATUS_CASE(NAME_NOT_FOUND);
+        STATUS_CASE(PERMISSION_DENIED);
+        STATUS_CASE(NO_INIT);
+        STATUS_CASE(ALREADY_EXISTS);
+        STATUS_CASE(DEAD_OBJECT);
+        STATUS_CASE(FAILED_TRANSACTION);
+        STATUS_CASE(BAD_INDEX);
+        STATUS_CASE(NOT_ENOUGH_DATA);
+        STATUS_CASE(WOULD_BLOCK);
+        STATUS_CASE(TIMED_OUT);
+        STATUS_CASE(UNKNOWN_TRANSACTION);
+        STATUS_CASE(FDS_NOT_ALLOWED);
+        STATUS_CASE(UNEXPECTED_NULL);
+#undef STATUS_CASE
+    }
+
+    return std::to_string(s) + " (" + strerror(-s) + ")";
+}
+
+}  // namespace android
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 2d696eb..14e3e35 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -14,7 +14,9 @@
 #define DEBUG_CALLBACKS 0
 
 #include <utils/Looper.h>
+
 #include <sys/eventfd.h>
+#include <cinttypes>
 
 namespace android {
 
diff --git a/libutils/Looper_test.cpp b/libutils/Looper_test.cpp
index 6fdc0ed..37bdf05 100644
--- a/libutils/Looper_test.cpp
+++ b/libutils/Looper_test.cpp
@@ -11,8 +11,9 @@
 
 #include <utils/threads.h>
 
+// b/141212746 - increased for virtual platforms with higher volatility
 // # of milliseconds to fudge stopwatch measurements
-#define TIMING_TOLERANCE_MS 25
+#define TIMING_TOLERANCE_MS 100
 
 namespace android {
 
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 7910c6e..3e703db 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -41,6 +41,7 @@
         // The following is OK on Android-supported platforms.
         sb->mRefs.store(1, std::memory_order_relaxed);
         sb->mSize = size;
+        sb->mClientMetadata = 0;
     }
     return sb;
 }
diff --git a/libutils/SharedBuffer.h b/libutils/SharedBuffer.h
index fdf13a9..476c842 100644
--- a/libutils/SharedBuffer.h
+++ b/libutils/SharedBuffer.h
@@ -102,7 +102,12 @@
         // Must be sized to preserve correct alignment.
         mutable std::atomic<int32_t>        mRefs;
                 size_t                      mSize;
-                uint32_t                    mReserved[2];
+                uint32_t                    mReserved;
+public:
+        // mClientMetadata is reserved for client use.  It is initialized to 0
+        // and the clients can do whatever they want with it.  Note that this is
+        // placed last so that it is adjcent to the buffer allocated.
+                uint32_t                    mClientMetadata;
 };
 
 static_assert(sizeof(SharedBuffer) % 8 == 0
diff --git a/libutils/String16.cpp b/libutils/String16.cpp
index 818b171..e2a8c59 100644
--- a/libutils/String16.cpp
+++ b/libutils/String16.cpp
@@ -24,21 +24,21 @@
 
 namespace android {
 
+static const StaticString16 emptyString(u"");
 static inline char16_t* getEmptyString() {
-    static SharedBuffer* gEmptyStringBuf = [] {
-        SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t));
-        char16_t* str = static_cast<char16_t*>(buf->data());
-        *str = 0;
-        return buf;
-    }();
-
-    gEmptyStringBuf->acquire();
-    return static_cast<char16_t*>(gEmptyStringBuf->data());
+    return const_cast<char16_t*>(emptyString.string());
 }
 
 // ---------------------------------------------------------------------------
 
-static char16_t* allocFromUTF8(const char* u8str, size_t u8len)
+void* String16::alloc(size_t size)
+{
+    SharedBuffer* buf = SharedBuffer::alloc(size);
+    buf->mClientMetadata = kIsSharedBufferAllocated;
+    return buf;
+}
+
+char16_t* String16::allocFromUTF8(const char* u8str, size_t u8len)
 {
     if (u8len == 0) return getEmptyString();
 
@@ -49,7 +49,7 @@
         return getEmptyString();
     }
 
-    SharedBuffer* buf = SharedBuffer::alloc(sizeof(char16_t)*(u16len+1));
+    SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t) * (u16len + 1)));
     if (buf) {
         u8cur = (const uint8_t*) u8str;
         char16_t* u16str = (char16_t*)buf->data();
@@ -66,13 +66,13 @@
     return getEmptyString();
 }
 
-static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len) {
+char16_t* String16::allocFromUTF16(const char16_t* u16str, size_t u16len) {
     if (u16len >= SIZE_MAX / sizeof(char16_t)) {
         android_errorWriteLog(0x534e4554, "73826242");
         abort();
     }
 
-    SharedBuffer* buf = SharedBuffer::alloc((u16len + 1) * sizeof(char16_t));
+    SharedBuffer* buf = static_cast<SharedBuffer*>(alloc((u16len + 1) * sizeof(char16_t)));
     ALOG_ASSERT(buf, "Unable to allocate shared buffer");
     if (buf) {
         char16_t* str = (char16_t*)buf->data();
@@ -97,8 +97,8 @@
     // having run. In this case we always allocate an empty string. It's less
     // efficient than using getEmptyString(), but we assume it's uncommon.
 
-    char16_t* data = static_cast<char16_t*>(
-            SharedBuffer::alloc(sizeof(char16_t))->data());
+    SharedBuffer* buf = static_cast<SharedBuffer*>(alloc(sizeof(char16_t)));
+    char16_t* data = static_cast<char16_t*>(buf->data());
     data[0] = 0;
     mString = data;
 }
@@ -106,7 +106,7 @@
 String16::String16(const String16& o)
     : mString(o.mString)
 {
-    SharedBuffer::bufferFromData(mString)->acquire();
+    acquire();
 }
 
 String16::String16(const String16& o, size_t len, size_t begin)
@@ -136,26 +136,30 @@
 
 String16::~String16()
 {
-    SharedBuffer::bufferFromData(mString)->release();
+    release();
 }
 
 size_t String16::size() const
 {
-    return SharedBuffer::sizeFromData(mString)/sizeof(char16_t)-1;
+    if (isStaticString()) {
+        return staticStringSize();
+    } else {
+        return SharedBuffer::sizeFromData(mString) / sizeof(char16_t) - 1;
+    }
 }
 
 void String16::setTo(const String16& other)
 {
-    SharedBuffer::bufferFromData(other.mString)->acquire();
-    SharedBuffer::bufferFromData(mString)->release();
+    release();
     mString = other.mString;
+    acquire();
 }
 
 status_t String16::setTo(const String16& other, size_t len, size_t begin)
 {
     const size_t N = other.size();
     if (begin >= N) {
-        SharedBuffer::bufferFromData(mString)->release();
+        release();
         mString = getEmptyString();
         return OK;
     }
@@ -184,8 +188,7 @@
         abort();
     }
 
-    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
-        ->editResize((len+1)*sizeof(char16_t));
+    SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
     if (buf) {
         char16_t* str = (char16_t*)buf->data();
         memmove(str, other, len*sizeof(char16_t));
@@ -212,8 +215,8 @@
         abort();
     }
 
-    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
-        ->editResize((myLen+otherLen+1)*sizeof(char16_t));
+    SharedBuffer* buf =
+            static_cast<SharedBuffer*>(editResize((myLen + otherLen + 1) * sizeof(char16_t)));
     if (buf) {
         char16_t* str = (char16_t*)buf->data();
         memcpy(str+myLen, other, (otherLen+1)*sizeof(char16_t));
@@ -238,8 +241,8 @@
         abort();
     }
 
-    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
-        ->editResize((myLen+otherLen+1)*sizeof(char16_t));
+    SharedBuffer* buf =
+            static_cast<SharedBuffer*>(editResize((myLen + otherLen + 1) * sizeof(char16_t)));
     if (buf) {
         char16_t* str = (char16_t*)buf->data();
         memcpy(str+myLen, chrs, otherLen*sizeof(char16_t));
@@ -273,8 +276,8 @@
            len, myLen, String8(chrs, len).string());
     #endif
 
-    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
-        ->editResize((myLen+len+1)*sizeof(char16_t));
+    SharedBuffer* buf =
+            static_cast<SharedBuffer*>(editResize((myLen + len + 1) * sizeof(char16_t)));
     if (buf) {
         char16_t* str = (char16_t*)buf->data();
         if (pos < myLen) {
@@ -338,23 +341,85 @@
     return strstr16(mString, chrs) != nullptr;
 }
 
+void* String16::edit() {
+    SharedBuffer* buf;
+    if (isStaticString()) {
+        buf = static_cast<SharedBuffer*>(alloc((size() + 1) * sizeof(char16_t)));
+        if (buf) {
+            memcpy(buf->data(), mString, (size() + 1) * sizeof(char16_t));
+        }
+    } else {
+        buf = SharedBuffer::bufferFromData(mString)->edit();
+        buf->mClientMetadata = kIsSharedBufferAllocated;
+    }
+    return buf;
+}
+
+void* String16::editResize(size_t newSize) {
+    SharedBuffer* buf;
+    if (isStaticString()) {
+        size_t copySize = (size() + 1) * sizeof(char16_t);
+        if (newSize < copySize) {
+            copySize = newSize;
+        }
+        buf = static_cast<SharedBuffer*>(alloc(newSize));
+        if (buf) {
+            memcpy(buf->data(), mString, copySize);
+        }
+    } else {
+        buf = SharedBuffer::bufferFromData(mString)->editResize(newSize);
+        buf->mClientMetadata = kIsSharedBufferAllocated;
+    }
+    return buf;
+}
+
+void String16::acquire()
+{
+    if (!isStaticString()) {
+        SharedBuffer::bufferFromData(mString)->acquire();
+    }
+}
+
+void String16::release()
+{
+    if (!isStaticString()) {
+        SharedBuffer::bufferFromData(mString)->release();
+    }
+}
+
+bool String16::isStaticString() const {
+    // See String16.h for notes on the memory layout of String16::StaticData and
+    // SharedBuffer.
+    static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
+    const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
+    return (*(p - 1) & kIsSharedBufferAllocated) == 0;
+}
+
+size_t String16::staticStringSize() const {
+    // See String16.h for notes on the memory layout of String16::StaticData and
+    // SharedBuffer.
+    static_assert(sizeof(SharedBuffer) - offsetof(SharedBuffer, mClientMetadata) == 4);
+    const uint32_t* p = reinterpret_cast<const uint32_t*>(mString);
+    return static_cast<size_t>(*(p - 1));
+}
+
 status_t String16::makeLower()
 {
     const size_t N = size();
     const char16_t* str = string();
-    char16_t* edit = nullptr;
+    char16_t* edited = nullptr;
     for (size_t i=0; i<N; i++) {
         const char16_t v = str[i];
         if (v >= 'A' && v <= 'Z') {
-            if (!edit) {
-                SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
+            if (!edited) {
+                SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
                 if (!buf) {
                     return NO_MEMORY;
                 }
-                edit = (char16_t*)buf->data();
-                mString = str = edit;
+                edited = (char16_t*)buf->data();
+                mString = str = edited;
             }
-            edit[i] = tolower((char)v);
+            edited[i] = tolower((char)v);
         }
     }
     return OK;
@@ -364,18 +429,18 @@
 {
     const size_t N = size();
     const char16_t* str = string();
-    char16_t* edit = nullptr;
+    char16_t* edited = nullptr;
     for (size_t i=0; i<N; i++) {
         if (str[i] == replaceThis) {
-            if (!edit) {
-                SharedBuffer* buf = SharedBuffer::bufferFromData(mString)->edit();
+            if (!edited) {
+                SharedBuffer* buf = static_cast<SharedBuffer*>(edit());
                 if (!buf) {
                     return NO_MEMORY;
                 }
-                edit = (char16_t*)buf->data();
-                mString = str = edit;
+                edited = (char16_t*)buf->data();
+                mString = str = edited;
             }
-            edit[i] = withThis;
+            edited[i] = withThis;
         }
     }
     return OK;
@@ -385,7 +450,7 @@
 {
     const size_t N = size();
     if (begin >= N) {
-        SharedBuffer::bufferFromData(mString)->release();
+        release();
         mString = getEmptyString();
         return OK;
     }
@@ -395,8 +460,7 @@
     }
 
     if (begin > 0) {
-        SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
-            ->editResize((N+1)*sizeof(char16_t));
+        SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((N + 1) * sizeof(char16_t)));
         if (!buf) {
             return NO_MEMORY;
         }
@@ -404,8 +468,7 @@
         memmove(str, str+begin, (N-begin+1)*sizeof(char16_t));
         mString = str;
     }
-    SharedBuffer* buf = SharedBuffer::bufferFromData(mString)
-        ->editResize((len+1)*sizeof(char16_t));
+    SharedBuffer* buf = static_cast<SharedBuffer*>(editResize((len + 1) * sizeof(char16_t)));
     if (buf) {
         char16_t* str = (char16_t*)buf->data();
         str[len] = 0;
diff --git a/libutils/String16_test.cpp b/libutils/String16_test.cpp
new file mode 100644
index 0000000..f1f24c3
--- /dev/null
+++ b/libutils/String16_test.cpp
@@ -0,0 +1,218 @@
+/*
+ * 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 <utils/String16.h>
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+
+::testing::AssertionResult Char16_tStringEquals(const char16_t* a, const char16_t* b) {
+    if (strcmp16(a, b) != 0) {
+        return ::testing::AssertionFailure()
+               << "\"" << String8(a).c_str() << "\" not equal to \"" << String8(b).c_str() << "\"";
+    }
+    return ::testing::AssertionSuccess();
+}
+
+#define EXPECT_STR16EQ(a, b) EXPECT_TRUE(Char16_tStringEquals(a, b))
+
+TEST(String16Test, FromChar16_t) {
+    String16 tmp(u"Verify me");
+    EXPECT_STR16EQ(u"Verify me", tmp);
+}
+
+TEST(String16Test, FromChar16_tSized) {
+    String16 tmp(u"Verify me", 7);
+    EXPECT_STR16EQ(u"Verify ", tmp);
+}
+
+TEST(String16Test, FromChar) {
+    String16 tmp("Verify me");
+    EXPECT_STR16EQ(u"Verify me", tmp);
+}
+
+TEST(String16Test, FromCharSized) {
+    String16 tmp("Verify me", 7);
+    EXPECT_STR16EQ(u"Verify ", tmp);
+}
+
+TEST(String16Test, Copy) {
+    String16 tmp("Verify me");
+    String16 another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp);
+    EXPECT_STR16EQ(u"Verify me", another);
+}
+
+TEST(String16Test, Move) {
+    String16 tmp("Verify me");
+    String16 another(std::move(tmp));
+    EXPECT_STR16EQ(u"Verify me", another);
+}
+
+TEST(String16Test, Size) {
+    String16 tmp("Verify me");
+    EXPECT_EQ(9U, tmp.size());
+}
+
+TEST(String16Test, setTo) {
+    String16 tmp("Verify me");
+    tmp.setTo(u"New content");
+    EXPECT_EQ(11U, tmp.size());
+    EXPECT_STR16EQ(u"New content", tmp);
+}
+
+TEST(String16Test, Append) {
+    String16 tmp("Verify me");
+    tmp.append(String16("Hello"));
+    EXPECT_EQ(14U, tmp.size());
+    EXPECT_STR16EQ(u"Verify meHello", tmp);
+}
+
+TEST(String16Test, Insert) {
+    String16 tmp("Verify me");
+    tmp.insert(6, u"Insert");
+    EXPECT_EQ(15U, tmp.size());
+    EXPECT_STR16EQ(u"VerifyInsert me", tmp);
+}
+
+TEST(String16Test, Remove) {
+    String16 tmp("Verify me");
+    tmp.remove(2, 6);
+    EXPECT_EQ(2U, tmp.size());
+    EXPECT_STR16EQ(u" m", tmp);
+}
+
+TEST(String16Test, MakeLower) {
+    String16 tmp("Verify Me!");
+    tmp.makeLower();
+    EXPECT_EQ(10U, tmp.size());
+    EXPECT_STR16EQ(u"verify me!", tmp);
+}
+
+TEST(String16Test, ReplaceAll) {
+    String16 tmp("Verify verify Verify");
+    tmp.replaceAll(u'r', u'!');
+    EXPECT_STR16EQ(u"Ve!ify ve!ify Ve!ify", tmp);
+}
+
+TEST(String16Test, Compare) {
+    String16 tmp("Verify me");
+    EXPECT_EQ(String16(u"Verify me"), tmp);
+}
+
+TEST(String16Test, StaticString) {
+    String16 nonStaticString("NonStatic");
+    StaticString16 staticString(u"Static");
+
+    EXPECT_TRUE(staticString.isStaticString());
+    EXPECT_FALSE(nonStaticString.isStaticString());
+}
+
+TEST(String16Test, StaticStringCopy) {
+    StaticString16 tmp(u"Verify me");
+    String16 another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp);
+    EXPECT_STR16EQ(u"Verify me", another);
+    EXPECT_TRUE(tmp.isStaticString());
+    EXPECT_TRUE(another.isStaticString());
+}
+
+TEST(String16Test, StaticStringMove) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(std::move(tmp));
+    EXPECT_STR16EQ(u"Verify me", another);
+    EXPECT_TRUE(another.isStaticString());
+}
+
+TEST(String16Test, StaticStringSize) {
+    StaticString16 tmp(u"Verify me");
+    EXPECT_EQ(9U, tmp.size());
+}
+
+TEST(String16Test, StaticStringSetTo) {
+    StaticString16 tmp(u"Verify me");
+    tmp.setTo(u"New content");
+    EXPECT_EQ(11U, tmp.size());
+    EXPECT_STR16EQ(u"New content", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringAppend) {
+    StaticString16 tmp(u"Verify me");
+    tmp.append(String16("Hello"));
+    EXPECT_EQ(14U, tmp.size());
+    EXPECT_STR16EQ(u"Verify meHello", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringInsert) {
+    StaticString16 tmp(u"Verify me");
+    tmp.insert(6, u"Insert");
+    EXPECT_EQ(15U, tmp.size());
+    EXPECT_STR16EQ(u"VerifyInsert me", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringRemove) {
+    StaticString16 tmp(u"Verify me");
+    tmp.remove(2, 6);
+    EXPECT_EQ(2U, tmp.size());
+    EXPECT_STR16EQ(u" m", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringMakeLower) {
+    StaticString16 tmp(u"Verify me!");
+    tmp.makeLower();
+    EXPECT_EQ(10U, tmp.size());
+    EXPECT_STR16EQ(u"verify me!", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringReplaceAll) {
+    StaticString16 tmp(u"Verify verify Verify");
+    tmp.replaceAll(u'r', u'!');
+    EXPECT_STR16EQ(u"Ve!ify ve!ify Ve!ify", tmp);
+    EXPECT_FALSE(tmp.isStaticString());
+}
+
+TEST(String16Test, StaticStringCompare) {
+    StaticString16 tmp(u"Verify me");
+    EXPECT_EQ(String16(u"Verify me"), tmp);
+}
+
+TEST(String16Test, StringSetToStaticString) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(u"nonstatic");
+    another = tmp;
+    EXPECT_STR16EQ(u"Verify me", tmp);
+    EXPECT_STR16EQ(u"Verify me", another);
+}
+
+TEST(String16Test, StringMoveFromStaticString) {
+    StaticString16 tmp(u"Verify me");
+    String16 another(std::move(tmp));
+    EXPECT_STR16EQ(u"Verify me", another);
+}
+
+TEST(String16Test, EmptyStringIsStatic) {
+    String16 tmp("");
+    EXPECT_TRUE(tmp.isStaticString());
+}
+
+}  // namespace android
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 0025c56..d13548e 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -468,21 +468,6 @@
     unlockBuffer(len);
 }
 
-size_t String8::getUtf32Length() const
-{
-    return utf8_to_utf32_length(mString, length());
-}
-
-int32_t String8::getUtf32At(size_t index, size_t *next_index) const
-{
-    return utf32_from_utf8_at(mString, length(), index, next_index);
-}
-
-void String8::getUtf32(char32_t* dst) const
-{
-    utf8_to_utf32(mString, length(), dst);
-}
-
 // ---------------------------------------------------------------------------
 // Path functions
 
diff --git a/libutils/StrongPointer.cpp b/libutils/StrongPointer.cpp
index ba52502..ef46723 100644
--- a/libutils/StrongPointer.cpp
+++ b/libutils/StrongPointer.cpp
@@ -21,4 +21,7 @@
 namespace android {
 
 void sp_report_race() { LOG_ALWAYS_FATAL("sp<> assignment detected data race"); }
+
+void sp_report_stack_pointer() { LOG_ALWAYS_FATAL("sp<> constructed with stack pointer argument"); }
+
 }
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index c3641ef..1172ae7 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -22,7 +22,8 @@
 #include <limits.h>
 #include <time.h>
 
-#if defined(__ANDROID__)
+// host linux support requires Linux 2.6.39+
+#if defined(__linux__)
 nsecs_t systemTime(int clock)
 {
     static const clockid_t clocks[] = {
@@ -41,8 +42,7 @@
 nsecs_t systemTime(int /*clock*/)
 {
     // Clock support varies widely across hosts. Mac OS doesn't support
-    // posix clocks, older glibcs don't support CLOCK_BOOTTIME and Windows
-    // is windows.
+    // CLOCK_BOOTTIME, and Windows is windows.
     struct timeval t;
     t.tv_sec = t.tv_usec = 0;
     gettimeofday(&t, nullptr);
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index 24a745a..b08e061 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -452,48 +452,6 @@
     *codePoint |= 0x3F & byte;
 }
 
-size_t utf8_to_utf32_length(const char *src, size_t src_len)
-{
-    if (src == nullptr || src_len == 0) {
-        return 0;
-    }
-    size_t ret = 0;
-    const char* cur;
-    const char* end;
-    size_t num_to_skip;
-    for (cur = src, end = src + src_len, num_to_skip = 1;
-         cur < end;
-         cur += num_to_skip, ret++) {
-        const char first_char = *cur;
-        num_to_skip = 1;
-        if ((first_char & 0x80) == 0) {  // ASCII
-            continue;
-        }
-        int32_t mask;
-
-        for (mask = 0x40; (first_char & mask); num_to_skip++, mask >>= 1) {
-        }
-    }
-    return ret;
-}
-
-void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst)
-{
-    if (src == nullptr || src_len == 0 || dst == nullptr) {
-        return;
-    }
-
-    const char* cur = src;
-    const char* const end = src + src_len;
-    char32_t* cur_utf32 = dst;
-    while (cur < end) {
-        size_t num_read;
-        *cur_utf32++ = static_cast<char32_t>(utf32_at_internal(cur, &num_read));
-        cur += num_read;
-    }
-    *cur_utf32 = 0;
-}
-
 static inline uint32_t utf8_to_utf32_codepoint(const uint8_t *src, size_t length)
 {
     uint32_t unicode;
diff --git a/libutils/Vector_benchmark.cpp b/libutils/Vector_benchmark.cpp
new file mode 100644
index 0000000..c23d499
--- /dev/null
+++ b/libutils/Vector_benchmark.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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 <benchmark/benchmark.h>
+#include <utils/Vector.h>
+#include <vector>
+
+void BM_fill_android_vector(benchmark::State& state) {
+    android::Vector<char> v;
+    while (state.KeepRunning()) {
+        v.push('A');
+    }
+}
+BENCHMARK(BM_fill_android_vector);
+
+void BM_fill_std_vector(benchmark::State& state) {
+    std::vector<char> v;
+    while (state.KeepRunning()) {
+        v.push_back('A');
+    }
+}
+BENCHMARK(BM_fill_std_vector);
+
+void BM_prepend_android_vector(benchmark::State& state) {
+    android::Vector<char> v;
+    while (state.KeepRunning()) {
+        v.insertAt('A', 0);
+    }
+}
+BENCHMARK(BM_prepend_android_vector);
+
+void BM_prepend_std_vector(benchmark::State& state) {
+    std::vector<char> v;
+    while (state.KeepRunning()) {
+        v.insert(v.begin(), 'A');
+    }
+}
+BENCHMARK(BM_prepend_std_vector);
+
+BENCHMARK_MAIN();
diff --git a/libutils/include/utils/ByteOrder.h b/libutils/include/utils/ByteOrder.h
index 44ea13d..9b940e6 100644
--- a/libutils/include/utils/ByteOrder.h
+++ b/libutils/include/utils/ByteOrder.h
@@ -14,10 +14,17 @@
  * limitations under the License.
  */
 
-//
+#pragma once
 
-#ifndef _LIBS_UTILS_BYTE_ORDER_H
-#define _LIBS_UTILS_BYTE_ORDER_H
+/*
+ * If you're looking for a portable <endian.h> that's available on Android,
+ * Linux, macOS, and Windows, see <android-base/endian.h> instead.
+ *
+ * Nothing in this file is useful because all supported Android ABIs are
+ * little-endian and all our code that runs on the host assumes that the host is
+ * also little-endian. What pretense at big-endian support exists is completely
+ * untested and unlikely to actually work.
+ */
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -27,55 +34,12 @@
 #include <netinet/in.h>
 #endif
 
-/*
- * These macros are like the hton/ntoh byte swapping macros,
- * except they allow you to swap to and from the "device" byte
- * order.  The device byte order is the endianness of the target
- * device -- for the ARM CPUs we use today, this is little endian.
- *
- * Note that the byte swapping functions have not been optimized
- * much; performance is currently not an issue for them since the
- * intent is to allow us to avoid byte swapping on the device.
- */
+/* TODO: move this cruft to frameworks/. */
 
-static inline uint32_t android_swap_long(uint32_t v)
-{
-    return (v<<24) | ((v<<8)&0x00FF0000) | ((v>>8)&0x0000FF00) | (v>>24);
-}
+#define dtohl(x) (x)
+#define dtohs(x) (x)
+#define htodl(x) (x)
+#define htods(x) (x)
 
-static inline uint16_t android_swap_short(uint16_t v)
-{
-    return (v<<8) | (v>>8);
-}
-
-#define DEVICE_BYTE_ORDER LITTLE_ENDIAN
-
-#if BYTE_ORDER == DEVICE_BYTE_ORDER
-
-#define	dtohl(x)	(x)
-#define	dtohs(x)	(x)
-#define	htodl(x)	(x)
-#define	htods(x)	(x)
-
-#else
-
-#define	dtohl(x)	(android_swap_long(x))
-#define	dtohs(x)	(android_swap_short(x))
-#define	htodl(x)	(android_swap_long(x))
-#define	htods(x)	(android_swap_short(x))
-
-#endif
-
-#if BYTE_ORDER == LITTLE_ENDIAN
 #define fromlel(x) (x)
-#define fromles(x) (x)
 #define tolel(x) (x)
-#define toles(x) (x)
-#else
-#define fromlel(x) (android_swap_long(x))
-#define fromles(x) (android_swap_short(x))
-#define tolel(x) (android_swap_long(x))
-#define toles(x) (android_swap_short(x))
-#endif
-
-#endif // _LIBS_UTILS_BYTE_ORDER_H
diff --git a/libutils/include/utils/Errors.h b/libutils/include/utils/Errors.h
index 1e03677..d14d223 100644
--- a/libutils/include/utils/Errors.h
+++ b/libutils/include/utils/Errors.h
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <string>
 
 namespace android {
 
@@ -72,6 +73,9 @@
     UNEXPECTED_NULL     = (UNKNOWN_ERROR + 8),
 };
 
+// Human readable name of error
+std::string statusToString(status_t status);
+
 // Restore define; enumeration is in "android" namespace, so the value defined
 // there won't work for Win32 code in a different namespace.
 #ifdef _WIN32
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 9d00602..953b859 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -17,6 +17,9 @@
 #ifndef ANDROID_UTILS_FLATTENABLE_H
 #define ANDROID_UTILS_FLATTENABLE_H
 
+// DO NOT USE: please use parcelable instead
+// This code is deprecated and will not be supported via AIDL code gen. For data
+// to be sent over binder, please use parcelables.
 
 #include <stdint.h>
 #include <string.h>
@@ -28,7 +31,9 @@
 
 namespace android {
 
-
+// DO NOT USE: please use parcelable instead
+// This code is deprecated and will not be supported via AIDL code gen. For data
+// to be sent over binder, please use parcelables.
 class FlattenableUtils {
 public:
     template<size_t N>
@@ -79,7 +84,9 @@
     }
 };
 
-
+// DO NOT USE: please use parcelable instead
+// This code is deprecated and will not be supported via AIDL code gen. For data
+// to be sent over binder, please use parcelables.
 /*
  * The Flattenable protocol allows an object to serialize itself out
  * to a byte-buffer and an array of file descriptors.
@@ -131,6 +138,9 @@
     return static_cast<T*>(this)->T::unflatten(buffer, size, fds, count);
 }
 
+// DO NOT USE: please use parcelable instead
+// This code is deprecated and will not be supported via AIDL code gen. For data
+// to be sent over binder, please use parcelables.
 /*
  * LightFlattenable is a protocol allowing object to serialize themselves out
  * to a byte-buffer. Because it doesn't handle file-descriptors,
@@ -171,6 +181,9 @@
     return static_cast<T*>(this)->T::unflatten(buffer, size);
 }
 
+// DO NOT USE: please use parcelable instead
+// This code is deprecated and will not be supported via AIDL code gen. For data
+// to be sent over binder, please use parcelables.
 /*
  * LightFlattenablePod is an implementation of the LightFlattenable protocol
  * for POD (plain-old-data) objects.
diff --git a/libutils/include/utils/LightRefBase.h b/libutils/include/utils/LightRefBase.h
index e488e60..b04e5c1 100644
--- a/libutils/include/utils/LightRefBase.h
+++ b/libutils/include/utils/LightRefBase.h
@@ -47,8 +47,6 @@
         return mCount.load(std::memory_order_relaxed);
     }
 
-    typedef LightRefBase<T> basetype;
-
 protected:
     inline ~LightRefBase() { }
 
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index a105474..89f048d 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -188,9 +188,6 @@
 // ---------------------------------------------------------------------------
 namespace android {
 
-class TextOutput;
-TextOutput& printWeakPointer(TextOutput& to, const void* val);
-
 // ---------------------------------------------------------------------------
 
 #define COMPARE_WEAK(_op_)                                      \
@@ -299,8 +296,6 @@
         getWeakRefs()->trackMe(enable, retain); 
     }
 
-    typedef RefBase basetype;
-
 protected:
                             RefBase();
     virtual                 ~RefBase();
@@ -459,10 +454,8 @@
     weakref_type*   m_refs;
 };
 
-template <typename T>
-TextOutput& operator<<(TextOutput& to, const wp<T>& val);
-
 #undef COMPARE_WEAK
+#undef COMPARE_WEAK_FUNCTIONAL
 
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
@@ -635,12 +628,6 @@
     }
 }
 
-template <typename T>
-inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
-{
-    return printWeakPointer(to, val.unsafe_get());
-}
-
 // ---------------------------------------------------------------------------
 
 // this class just serves as a namespace so TYPE::moveReferences can stay
diff --git a/libutils/include/utils/String16.h b/libutils/include/utils/String16.h
index afbc2ed..adc3e7d 100644
--- a/libutils/include/utils/String16.h
+++ b/libutils/include/utils/String16.h
@@ -37,13 +37,17 @@
 
 class String8;
 
+template <size_t N>
+class StaticString16;
+
 // DO NOT USE: please use std::u16string
 
 //! This is a string holding UTF-16 characters.
 class String16
 {
 public:
-    /* use String16(StaticLinkage) if you're statically linking against
+    /*
+     * Use String16(StaticLinkage) if you're statically linking against
      * libutils and declaring an empty static String16, e.g.:
      *
      *   static String16 sAStaticEmptyString(String16::kEmptyString);
@@ -123,8 +127,76 @@
 
     inline                      operator const char16_t*() const;
 
-private:
-            const char16_t*     mString;
+    // Static and non-static String16 behave the same for the users, so
+    // this method isn't of much use for the users. It is public for testing.
+            bool                isStaticString() const;
+
+  private:
+    /*
+     * A flag indicating the type of underlying buffer.
+     */
+    static constexpr uint32_t kIsSharedBufferAllocated = 0x80000000;
+
+    /*
+     * alloc() returns void* so that SharedBuffer class is not exposed.
+     */
+    static void* alloc(size_t size);
+    static char16_t* allocFromUTF8(const char* u8str, size_t u8len);
+    static char16_t* allocFromUTF16(const char16_t* u16str, size_t u16len);
+
+    /*
+     * edit() and editResize() return void* so that SharedBuffer class
+     * is not exposed.
+     */
+    void* edit();
+    void* editResize(size_t new_size);
+
+    void acquire();
+    void release();
+
+    size_t staticStringSize() const;
+
+    const char16_t* mString;
+
+protected:
+    /*
+     * Data structure used to allocate static storage for static String16.
+     *
+     * Note that this data structure and SharedBuffer are used interchangably
+     * as the underlying data structure for a String16.  Therefore, the layout
+     * of this data structure must match the part in SharedBuffer that is
+     * visible to String16.
+     */
+    template <size_t N>
+    struct StaticData {
+        // The high bit of 'size' is used as a flag.
+        static_assert(N - 1 < kIsSharedBufferAllocated, "StaticString16 too long!");
+        constexpr StaticData() : size(N - 1), data{0} {}
+        const uint32_t size;
+        char16_t data[N];
+
+        constexpr StaticData(const StaticData<N>&) = default;
+    };
+
+    /*
+     * Helper function for constructing a StaticData object.
+     */
+    template <size_t N>
+    static constexpr const StaticData<N> makeStaticData(const char16_t (&s)[N]) {
+        StaticData<N> r;
+        // The 'size' field is at the same location where mClientMetadata would
+        // be for a SharedBuffer.  We do NOT set kIsSharedBufferAllocated flag
+        // here.
+        for (size_t i = 0; i < N - 1; ++i) r.data[i] = s[i];
+        return r;
+    }
+
+    template <size_t N>
+    explicit constexpr String16(const StaticData<N>& s) : mString(s.data) {}
+
+public:
+    template <size_t N>
+    explicit constexpr String16(const StaticString16<N>& s) : mString(s.mString) {}
 };
 
 // String16 can be trivially moved using memcpy() because moving does not
@@ -132,6 +204,42 @@
 ANDROID_TRIVIAL_MOVE_TRAIT(String16)
 
 // ---------------------------------------------------------------------------
+
+/*
+ * A StaticString16 object is a specialized String16 object.  Instead of holding
+ * the string data in a ref counted SharedBuffer object, it holds data in a
+ * buffer within StaticString16 itself.  Note that this buffer is NOT ref
+ * counted and is assumed to be available for as long as there is at least a
+ * String16 object using it.  Therefore, one must be extra careful to NEVER
+ * assign a StaticString16 to a String16 that outlives the StaticString16
+ * object.
+ *
+ * THE SAFEST APPROACH IS TO USE StaticString16 ONLY AS GLOBAL VARIABLES.
+ *
+ * A StaticString16 SHOULD NEVER APPEAR IN APIs.  USE String16 INSTEAD.
+ */
+template <size_t N>
+class StaticString16 : public String16 {
+public:
+    constexpr StaticString16(const char16_t (&s)[N]) : String16(mData), mData(makeStaticData(s)) {}
+
+    constexpr StaticString16(const StaticString16<N>& other)
+        : String16(mData), mData(other.mData) {}
+
+    constexpr StaticString16(const StaticString16<N>&&) = delete;
+
+    // There is no reason why one would want to 'new' a StaticString16.  Delete
+    // it to discourage misuse.
+    static void* operator new(std::size_t) = delete;
+
+private:
+    const StaticData<N> mData;
+};
+
+template <typename F>
+StaticString16(const F&)->StaticString16<sizeof(F) / sizeof(char16_t)>;
+
+// ---------------------------------------------------------------------------
 // No user servicable parts below.
 
 inline int compare_type(const String16& lhs, const String16& rhs)
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index c8f584e..0ddcbb2 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -95,13 +95,6 @@
                     __attribute__((format (printf, 2, 3)));
             status_t            appendFormatV(const char* fmt, va_list args);
 
-            // Note that this function takes O(N) time to calculate the value.
-            // No cache value is stored.
-            size_t              getUtf32Length() const;
-            int32_t             getUtf32At(size_t index,
-                                           size_t *next_index) const;
-            void                getUtf32(char32_t* dst) const;
-
     inline  String8&            operator=(const String8& other);
     inline  String8&            operator=(const char* other);
 
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 9cd7c75..100e507 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -122,26 +122,55 @@
         return o != *this;
     }
 
-private:    
+private:
     template<typename Y> friend class sp;
     template<typename Y> friend class wp;
     void set_pointer(T* ptr);
+    static inline void check_not_on_stack(const void* ptr);
     T* m_ptr;
 };
 
-// For code size reasons, we do not want this inlined or templated.
+// For code size reasons, we do not want these inlined or templated.
 void sp_report_race();
+void sp_report_stack_pointer();
 
-#undef COMPARE
+#undef COMPARE_STRONG
+#undef COMPARE_STRONG_FUNCTIONAL
 
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
 
+// Check whether address is definitely on the calling stack.  We actually check whether it is on
+// the same 4K page as the frame pointer.
+//
+// Assumptions:
+// - Pages are never smaller than 4K (MIN_PAGE_SIZE)
+// - Malloced memory never shares a page with a stack.
+//
+// It does not appear safe to broaden this check to include adjacent pages; apparently this code
+// is used in environments where there may not be a guard page below (at higher addresses than)
+// the bottom of the stack.
+//
+// TODO: Consider adding make_sp<T>() to allocate an object and wrap the resulting pointer safely
+// without checking overhead.
+template <typename T>
+void sp<T>::check_not_on_stack(const void* ptr) {
+    static constexpr int MIN_PAGE_SIZE = 0x1000;  // 4K. Safer than including sys/user.h.
+    static constexpr uintptr_t MIN_PAGE_MASK = ~static_cast<uintptr_t>(MIN_PAGE_SIZE - 1);
+    uintptr_t my_frame_address =
+            reinterpret_cast<uintptr_t>(__builtin_frame_address(0 /* this frame */));
+    if (((reinterpret_cast<uintptr_t>(ptr) ^ my_frame_address) & MIN_PAGE_MASK) == 0) {
+        sp_report_stack_pointer();
+    }
+}
+
 template<typename T>
 sp<T>::sp(T* other)
         : m_ptr(other) {
-    if (other)
+    if (other) {
+        check_not_on_stack(other);
         other->incStrong(this);
+    }
 }
 
 template<typename T>
@@ -159,8 +188,10 @@
 template<typename T> template<typename U>
 sp<T>::sp(U* other)
         : m_ptr(other) {
-    if (other)
+    if (other) {
+        check_not_on_stack(other);
         (static_cast<T*>(other))->incStrong(this);
+    }
 }
 
 template<typename T> template<typename U>
@@ -207,7 +238,10 @@
 template<typename T>
 sp<T>& sp<T>::operator =(T* other) {
     T* oldPtr(*const_cast<T* volatile*>(&m_ptr));
-    if (other) other->incStrong(this);
+    if (other) {
+        check_not_on_stack(other);
+        other->incStrong(this);
+    }
     if (oldPtr) oldPtr->decStrong(this);
     if (oldPtr != *const_cast<T* volatile*>(&m_ptr)) sp_report_race();
     m_ptr = other;
diff --git a/libutils/include/utils/Trace.h b/libutils/include/utils/Trace.h
index 4b9c91e..9986bf5 100644
--- a/libutils/include/utils/Trace.h
+++ b/libutils/include/utils/Trace.h
@@ -17,7 +17,12 @@
 #ifndef ANDROID_TRACE_H
 #define ANDROID_TRACE_H
 
-#if defined(__ANDROID__)
+#if defined(_WIN32)
+
+#define ATRACE_NAME(...)
+#define ATRACE_CALL()
+
+#else  // !_WIN32
 
 #include <stdint.h>
 
@@ -28,7 +33,7 @@
 // ATRACE_NAME traces from its location until the end of its enclosing scope.
 #define _PASTE(x, y) x ## y
 #define PASTE(x, y) _PASTE(x,y)
-#define ATRACE_NAME(name) android::ScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
+#define ATRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name)
 
 // ATRACE_CALL is an ATRACE_NAME that uses the current function name.
 #define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
@@ -51,11 +56,6 @@
 
 }  // namespace android
 
-#else // !__ANDROID__
-
-#define ATRACE_NAME(...)
-#define ATRACE_CALL()
-
-#endif // __ANDROID__
+#endif  // _WIN32
 
 #endif // ANDROID_TRACE_H
diff --git a/libutils/include/utils/Unicode.h b/libutils/include/utils/Unicode.h
index a2aaa47..fc6712d 100644
--- a/libutils/include/utils/Unicode.h
+++ b/libutils/include/utils/Unicode.h
@@ -129,18 +129,6 @@
 ssize_t utf8_length(const char *src);
 
 /**
- * Measure the length of a UTF-32 string.
- */
-size_t utf8_to_utf32_length(const char *src, size_t src_len);
-
-/**
- * Stores a UTF-32 string converted from "src" in "dst". "dst" must be large
- * enough to store the entire converted string as measured by
- * utf8_to_utf32_length plus space for a NUL terminator.
- */
-void utf8_to_utf32(const char* src, size_t src_len, char32_t* dst);
-
-/**
  * Returns the UTF-16 length of UTF-8 string "src". Returns -1 in case
  * it's invalid utf8. No buffer over-read occurs because of bound checks. Using overreadIsFatal you
  * can ask to log a message and fail in case the invalid utf8 could have caused an override if no
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
index 546c15c..f4544a1 100644
--- a/libvndksupport/Android.bp
+++ b/libvndksupport/Android.bp
@@ -2,7 +2,8 @@
 
 cc_library {
     name: "libvndksupport",
-    srcs: ["linker.c"],
+    native_bridge_supported: true,
+    srcs: ["linker.cpp"],
     cflags: [
         "-Wall",
         "-Werror",
@@ -22,6 +23,7 @@
 
 llndk_library {
     name: "libvndksupport",
+    native_bridge_supported: true,
     symbol_file: "libvndksupport.map.txt",
     export_include_dirs: ["include"],
 }
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
index ac9a99c..a44ed18 100644
--- a/libvndksupport/libvndksupport.map.txt
+++ b/libvndksupport/libvndksupport.map.txt
@@ -1,8 +1,8 @@
 LIBVNDKSUPPORT {
   global:
-    android_is_in_vendor_process; # vndk apex
-    android_load_sphal_library; # vndk apex
-    android_unload_sphal_library; # vndk apex
+    android_is_in_vendor_process; # llndk apex
+    android_load_sphal_library; # llndk apex
+    android_unload_sphal_library; # llndk apex
   local:
     *;
 };
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
deleted file mode 100644
index 84c2132..0000000
--- a/libvndksupport/linker.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2017 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 "linker.h"
-
-#include <android/dlext.h>
-#include <dlfcn.h>
-
-#define LOG_TAG "vndksupport"
-#include <log/log.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-__attribute__((weak)) extern struct android_namespace_t* android_get_exported_namespace(const char*);
-__attribute__((weak)) extern void* android_dlopen_ext(const char*, int, const android_dlextinfo*);
-
-static const char* namespace_name = NULL;
-
-static struct android_namespace_t* get_vendor_namespace() {
-    const char* namespace_names[] = {"sphal", "default", NULL};
-    static struct android_namespace_t* vendor_namespace = NULL;
-    if (vendor_namespace == NULL) {
-        int name_idx = 0;
-        while (namespace_names[name_idx] != NULL) {
-            if (android_get_exported_namespace != NULL) {
-                vendor_namespace = android_get_exported_namespace(namespace_names[name_idx]);
-            }
-            if (vendor_namespace != NULL) {
-                namespace_name = namespace_names[name_idx];
-                break;
-            }
-            name_idx++;
-        }
-    }
-    return vendor_namespace;
-}
-
-int android_is_in_vendor_process() {
-    // Special case init, since when init runs, ld.config.<ver>.txt hasn't been
-    // loaded (sysprop service isn't up for init to know <ver>).
-    if (getpid() == 1) {
-        return 0;
-    }
-    if (android_get_exported_namespace == NULL) {
-        ALOGD("android_get_exported_namespace() not available. Assuming system process.");
-        return 0;
-    }
-
-    // In vendor process, 'vndk' namespace is not visible, whereas in system
-    // process, it is.
-    return android_get_exported_namespace("vndk") == NULL;
-}
-
-void* android_load_sphal_library(const char* name, int flag) {
-    struct android_namespace_t* vendor_namespace = get_vendor_namespace();
-    if (vendor_namespace != NULL) {
-        const android_dlextinfo dlextinfo = {
-            .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = vendor_namespace,
-        };
-        void* handle = NULL;
-        if (android_dlopen_ext != NULL) {
-            handle = android_dlopen_ext(name, flag, &dlextinfo);
-        }
-        if (!handle) {
-            ALOGE("Could not load %s from %s namespace: %s.", name, namespace_name, dlerror());
-        }
-        return handle;
-    } else {
-        ALOGD("Loading %s from current namespace instead of sphal namespace.", name);
-        return dlopen(name, flag);
-    }
-}
-
-int android_unload_sphal_library(void* handle) {
-    return dlclose(handle);
-}
diff --git a/libvndksupport/linker.cpp b/libvndksupport/linker.cpp
new file mode 100644
index 0000000..30b9c2e
--- /dev/null
+++ b/libvndksupport/linker.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 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 "vndksupport"
+
+#include "linker.h"
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+#include <log/log.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <initializer_list>
+
+extern "C" android_namespace_t* android_get_exported_namespace(const char*);
+
+namespace {
+
+struct VendorNamespace {
+    android_namespace_t* ptr = nullptr;
+    const char* name = nullptr;
+};
+
+}  // anonymous namespace
+
+static VendorNamespace get_vendor_namespace() {
+    static VendorNamespace result = ([] {
+        for (const char* name : {"sphal", "default"}) {
+            if (android_namespace_t* ns = android_get_exported_namespace(name)) {
+                return VendorNamespace{ns, name};
+            }
+        }
+        return VendorNamespace{};
+    })();
+    return result;
+}
+
+int android_is_in_vendor_process() {
+    // Special case init, since when init runs, ld.config.<ver>.txt hasn't been
+    // loaded (sysprop service isn't up for init to know <ver>).
+    if (getpid() == 1) {
+        return 0;
+    }
+
+    // In vendor process, 'vndk' namespace is not visible, whereas in system
+    // process, it is.
+    return android_get_exported_namespace("vndk") == nullptr;
+}
+
+void* android_load_sphal_library(const char* name, int flag) {
+    VendorNamespace vendor_namespace = get_vendor_namespace();
+    if (vendor_namespace.ptr != nullptr) {
+        const android_dlextinfo dlextinfo = {
+                .flags = ANDROID_DLEXT_USE_NAMESPACE,
+                .library_namespace = vendor_namespace.ptr,
+        };
+        void* handle = android_dlopen_ext(name, flag, &dlextinfo);
+        if (!handle) {
+            ALOGE("Could not load %s from %s namespace: %s.", name, vendor_namespace.name,
+                  dlerror());
+        }
+        return handle;
+    } else {
+        ALOGD("Loading %s from current namespace instead of sphal namespace.", name);
+        return dlopen(name, flag);
+    }
+}
+
+int android_unload_sphal_library(void* handle) {
+    return dlclose(handle);
+}
diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp
index 7ce27d4..d0c8ef7 100644
--- a/libvndksupport/tests/linker_test.cpp
+++ b/libvndksupport/tests/linker_test.cpp
@@ -21,11 +21,6 @@
 #include <vndksupport/linker.h>
 #include <string>
 
-// Since the test executable will be in /data and ld.config.txt does not
-// configure sphal namespace for executables in /data, the call to
-// android_load_sphal_library will always fallback to the plain dlopen from the
-// default namespace.
-
 // Let's use libEGL_<chipset>.so as a SP-HAL in test
 static std::string find_sphal_lib() {
     const char* path =
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index bc1543b..1bbffaf 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -26,6 +26,8 @@
         // Incorrectly warns when C++11 empty brace {} initializer is used.
         // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
         "-Wno-missing-field-initializers",
+        "-Wconversion",
+        "-Wno-sign-conversion",
     ],
 
     // Enable -Wold-style-cast only for non-Windows targets.  _islower_l,
@@ -74,6 +76,10 @@
         "liblog",
     ],
 
+    // for FRIEND_TEST
+    static_libs: ["libgtest_prod"],
+    export_static_lib_headers: ["libgtest_prod"],
+
     export_include_dirs: ["include"],
 }
 
@@ -82,6 +88,7 @@
     host_supported: true,
     vendor_available: true,
     recovery_available: true,
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
@@ -168,12 +175,38 @@
 }
 
 cc_binary {
-    name: "unzip",
+    name: "ziptool",
     defaults: ["libziparchive_flags"],
-    srcs: ["unzip.cpp"],
+    srcs: ["ziptool.cpp"],
     shared_libs: [
         "libbase",
         "libziparchive",
     ],
     recovery_available: true,
+    host_supported: true,
+    target: {
+        android: {
+            symlinks: ["unzip", "zipinfo"],
+        },
+    },
+}
+
+cc_fuzz {
+    name: "libziparchive_fuzzer",
+    srcs: ["libziparchive_fuzzer.cpp"],
+    static_libs: ["libziparchive", "libbase", "libz", "liblog"],
+    host_supported: true,
+    corpus: ["testdata/*"],
+}
+
+sh_test {
+    name: "ziptool-tests",
+    src: "run-ziptool-tests-on-android.sh",
+    filename: "run-ziptool-tests-on-android.sh",
+    test_suites: ["general-tests"],
+    host_supported: true,
+    device_supported: false,
+    test_config: "ziptool-tests.xml",
+    data: ["cli-tests/**/*"],
+    target_required: ["cli-test", "ziptool"],
 }
diff --git a/libziparchive/cli-tests/files/example.zip b/libziparchive/cli-tests/files/example.zip
new file mode 100644
index 0000000..c3292e9
--- /dev/null
+++ b/libziparchive/cli-tests/files/example.zip
Binary files differ
diff --git a/libziparchive/cli-tests/unzip.test b/libziparchive/cli-tests/unzip.test
new file mode 100755
index 0000000..6e5cbf2
--- /dev/null
+++ b/libziparchive/cli-tests/unzip.test
@@ -0,0 +1,148 @@
+# unzip tests.
+
+# Note: since "master key", Android uses libziparchive for all zip file
+# handling, and that scans the whole central directory immediately. Not only
+# lookups by name but also iteration is implemented using the resulting hash
+# table, meaning that any test that makes assumptions about iteration order
+# will fail on Android.
+
+name: unzip -l
+command: unzip -l $FILES/example.zip d1/d2/x.txt
+after: [ ! -f d1/d2/x.txt ]
+expected-stdout:
+	Archive:  $FILES/example.zip
+	  Length      Date    Time    Name
+	---------  ---------- -----   ----
+	     1024  2017-06-04 08:45   d1/d2/x.txt
+	---------                     -------
+	     1024                     1 file
+---
+
+name: unzip -lq
+command: unzip -lq $FILES/example.zip d1/d2/x.txt
+after: [ ! -f d1/d2/x.txt ]
+expected-stdout:
+	  Length      Date    Time    Name
+	---------  ---------- -----   ----
+	     1024  2017-06-04 08:45   d1/d2/x.txt
+	---------                     -------
+	     1024                     1 file
+---
+
+name: unzip -lv
+command: unzip -lv $FILES/example.zip d1/d2/x.txt
+after: [ ! -f d1/d2/file ]
+expected-stdout:
+	Archive:  $FILES/example.zip
+	 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
+	--------  ------  ------- ---- ---------- ----- --------  ----
+	    1024  Defl:N       11  99% 2017-06-04 08:45 48d7f063  d1/d2/x.txt
+	--------          -------  ---                            -------
+	    1024               11  99%                            1 file
+---
+
+name: unzip -v
+command: unzip -v $FILES/example.zip d1/d2/x.txt
+after: [ ! -f d1/d2/file ]
+expected-stdout:
+	Archive:  $FILES/example.zip
+	 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
+	--------  ------  ------- ---- ---------- ----- --------  ----
+	    1024  Defl:N       11  99% 2017-06-04 08:45 48d7f063  d1/d2/x.txt
+	--------          -------  ---                            -------
+	    1024               11  99%                            1 file
+---
+
+name: unzip one file
+command: unzip -q $FILES/example.zip d1/d2/a.txt && cat d1/d2/a.txt
+after: [ ! -f d1/d2/b.txt ]
+expected-stdout:
+	a
+---
+
+name: unzip all files
+command: unzip -q $FILES/example.zip
+after: [ -f d1/d2/a.txt ]
+after: [ -f d1/d2/b.txt ]
+after: [ -f d1/d2/c.txt ]
+after: [ -f d1/d2/empty.txt ]
+after: [ -f d1/d2/x.txt ]
+after: [ -d d1/d2/dir ]
+expected-stdout:
+---
+
+name: unzip -o
+before: mkdir -p d1/d2
+before: echo b > d1/d2/a.txt
+command: unzip -q -o $FILES/example.zip d1/d2/a.txt && cat d1/d2/a.txt
+expected-stdout:
+	a
+---
+
+name: unzip -n
+before: mkdir -p d1/d2
+before: echo b > d1/d2/a.txt
+command: unzip -q -n $FILES/example.zip d1/d2/a.txt && cat d1/d2/a.txt
+expected-stdout:
+	b
+---
+
+# The reference implementation will create *one* level of missing directories,
+# so this succeeds.
+name: unzip -d shallow non-existent
+command: unzip -q -d will-be-created $FILES/example.zip d1/d2/a.txt
+after: [ -d will-be-created ]
+after: [ -f will-be-created/d1/d2/a.txt ]
+---
+
+# The reference implementation will *only* create one level of missing
+# directories, so this fails.
+name: unzip -d deep non-existent
+command: unzip -q -d oh-no/will-not-be-created $FILES/example.zip d1/d2/a.txt 2> stderr ; echo $? > status
+after: [ ! -d oh-no ]
+after: [ ! -d oh-no/will-not-be-created ]
+after: [ ! -f oh-no/will-not-be-created/d1/d2/a.txt ]
+after: grep -q "oh-no/will-not-be-created" stderr
+after: grep -q "No such file or directory" stderr
+# The reference implementation has *lots* of non-zero exit values, but we stick to 0 and 1.
+after: [ $(cat status) -gt 0 ]
+---
+
+name: unzip -d exists
+before: mkdir dir
+command: unzip -q -d dir $FILES/example.zip d1/d2/a.txt && cat dir/d1/d2/a.txt
+after: [ ! -f d1/d2/a.txt ]
+expected-stdout:
+	a
+---
+
+name: unzip -p
+command: unzip -p $FILES/example.zip d1/d2/a.txt
+after: [ ! -f d1/d2/a.txt ]
+expected-stdout:
+	a
+---
+
+name: unzip -x FILE...
+# Note: the RI ignores -x DIR for some reason, but it's not obvious we should.
+command: unzip -q $FILES/example.zip -x d1/d2/a.txt d1/d2/b.txt d1/d2/empty.txt d1/d2/x.txt && cat d1/d2/c.txt
+after: [ ! -f d1/d2/a.txt ]
+after: [ ! -f d1/d2/b.txt ]
+after: [ ! -f d1/d2/empty.txt ]
+after: [ ! -f d1/d2/x.txt ]
+after: [ -d d1/d2/dir ]
+expected-stdout:
+	ccc
+---
+
+name: unzip FILE -x FILE...
+command: unzip -q $FILES/example.zip d1/d2/a.txt d1/d2/b.txt -x d1/d2/a.txt && cat d1/d2/b.txt
+after: [ ! -f d1/d2/a.txt ]
+after: [ -f d1/d2/b.txt ]
+after: [ ! -f d1/d2/c.txt ]
+after: [ ! -f d1/d2/empty.txt ]
+after: [ ! -f d1/d2/x.txt ]
+after: [ ! -d d1/d2/dir ]
+expected-stdout:
+	bb
+---
diff --git a/libziparchive/cli-tests/zipinfo.test b/libziparchive/cli-tests/zipinfo.test
new file mode 100755
index 0000000..d5bce1c
--- /dev/null
+++ b/libziparchive/cli-tests/zipinfo.test
@@ -0,0 +1,53 @@
+# zipinfo tests.
+
+# Note: since "master key", Android uses libziparchive for all zip file
+# handling, and that scans the whole central directory immediately. Not only
+# lookups by name but also iteration is implemented using the resulting hash
+# table, meaning that any test that makes assumptions about iteration order
+# will fail on Android.
+
+name: zipinfo -1
+command: zipinfo -1 $FILES/example.zip | sort
+expected-stdout:
+	d1/
+	d1/d2/a.txt
+	d1/d2/b.txt
+	d1/d2/c.txt
+	d1/d2/dir/
+	d1/d2/empty.txt
+	d1/d2/x.txt
+---
+
+name: zipinfo header
+command: zipinfo $FILES/example.zip | head -2
+expected-stdout:
+	Archive:  $FILES/example.zip
+	Zip file size: 1082 bytes, number of entries: 7
+---
+
+name: zipinfo footer
+command: zipinfo $FILES/example.zip | tail -1
+expected-stdout:
+	7 files, 1033 bytes uncompressed, 20 bytes compressed:  98.1%
+---
+
+name: zipinfo directory
+# The RI doesn't use ISO dates.
+command: zipinfo $FILES/example.zip d1/ | sed s/17-Jun-/2017-06-/
+expected-stdout:
+	drwxr-x---  3.0 unx        0 bx stor 2017-06-04 08:40 d1/
+---
+
+name: zipinfo stored
+# The RI doesn't use ISO dates.
+command: zipinfo $FILES/example.zip d1/d2/empty.txt | sed s/17-Jun-/2017-06-/
+expected-stdout:
+	-rw-r-----  3.0 unx        0 bx stor 2017-06-04 08:43 d1/d2/empty.txt
+---
+
+name: zipinfo deflated
+# The RI doesn't use ISO dates.
+command: zipinfo $FILES/example.zip d1/d2/x.txt | sed s/17-Jun-/2017-06-/
+expected-stdout:
+	-rw-r-----  3.0 unx     1024 tx defN 2017-06-04 08:45 d1/d2/x.txt
+---
diff --git a/libziparchive/entry_name_utils-inl.h b/libziparchive/entry_name_utils-inl.h
index 1714586..10311b5 100644
--- a/libziparchive/entry_name_utils-inl.h
+++ b/libziparchive/entry_name_utils-inl.h
@@ -20,9 +20,15 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <limits>
+
 // Check if |length| bytes at |entry_name| constitute a valid entry name.
-// Entry names must be valid UTF-8 and must not contain '0'.
+// Entry names must be valid UTF-8 and must not contain '0'. They also must
+// fit into the central directory record.
 inline bool IsValidEntryName(const uint8_t* entry_name, const size_t length) {
+  if (length > std::numeric_limits<uint16_t>::max()) {
+    return false;
+  }
   for (size_t i = 0; i < length; ++i) {
     const uint8_t byte = entry_name[i];
     if (byte == 0) {
@@ -35,7 +41,8 @@
       return false;
     } else {
       // 2-5 byte sequences.
-      for (uint8_t first = (byte & 0x7f) << 1; first & 0x80; first = (first & 0x7f) << 1) {
+      for (uint8_t first = static_cast<uint8_t>((byte & 0x7f) << 1); first & 0x80;
+           first = static_cast<uint8_t>((first & 0x7f) << 1)) {
         ++i;
 
         // Missing continuation byte..
diff --git a/libziparchive/include/ziparchive/zip_archive.h b/libziparchive/include/ziparchive/zip_archive.h
index ab38dfd..047af90 100644
--- a/libziparchive/include/ziparchive/zip_archive.h
+++ b/libziparchive/include/ziparchive/zip_archive.h
@@ -25,6 +25,9 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
+#include <string>
+#include <string_view>
+
 #include "android-base/off64_t.h"
 
 /* Zip compression methods we support */
@@ -33,38 +36,12 @@
   kCompressDeflated = 8,  // standard deflate
 };
 
-struct ZipString {
-  const uint8_t* name;
-  uint16_t name_length;
-
-  ZipString() {}
-
-  /*
-   * entry_name has to be an c-style string with only ASCII characters.
-   */
-  explicit ZipString(const char* entry_name);
-
-  bool operator==(const ZipString& rhs) const {
-    return name && (name_length == rhs.name_length) && (memcmp(name, rhs.name, name_length) == 0);
-  }
-
-  bool StartsWith(const ZipString& prefix) const {
-    return name && (name_length >= prefix.name_length) &&
-           (memcmp(name, prefix.name, prefix.name_length) == 0);
-  }
-
-  bool EndsWith(const ZipString& suffix) const {
-    return name && (name_length >= suffix.name_length) &&
-           (memcmp(name + name_length - suffix.name_length, suffix.name, suffix.name_length) == 0);
-  }
-};
-
 /*
  * Represents information about a zip entry in a zip file.
  */
 struct ZipEntry {
-  // Compression method: One of kCompressStored or
-  // kCompressDeflated.
+  // Compression method. One of kCompressStored or kCompressDeflated.
+  // See also `gpbf` for deflate subtypes.
   uint16_t method;
 
   // Modification time. The zipfile format specifies
@@ -78,7 +55,7 @@
   struct tm GetModificationTime() const;
 
   // Suggested Unix mode for this entry, from the zip archive if created on
-  // Unix, or a default otherwise.
+  // Unix, or a default otherwise. See also `external_file_attributes`.
   mode_t unix_mode;
 
   // 1 if this entry contains a data descriptor segment, 0
@@ -102,6 +79,18 @@
 
   // The offset to the start of data for this ZipEntry.
   off64_t offset;
+
+  // The version of zip and the host file system this came from (for zipinfo).
+  uint16_t version_made_by;
+
+  // The raw attributes, whose interpretation depends on the host
+  // file system in `version_made_by` (for zipinfo). See also `unix_mode`.
+  uint32_t external_file_attributes;
+
+  // Specifics about the deflation (for zipinfo).
+  uint16_t gpbf;
+  // Whether this entry is believed to be text or binary (for zipinfo).
+  bool is_text;
 };
 
 struct ZipArchive;
@@ -137,7 +126,7 @@
 int32_t OpenArchiveFd(const int fd, const char* debugFileName, ZipArchiveHandle* handle,
                       bool assume_ownership = true);
 
-int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debugFileName,
+int32_t OpenArchiveFromMemory(const void* address, size_t length, const char* debugFileName,
                               ZipArchiveHandle* handle);
 /*
  * Close archive, releasing resources associated with it. This will
@@ -148,9 +137,21 @@
  */
 void CloseArchive(ZipArchiveHandle archive);
 
+/** See GetArchiveInfo(). */
+struct ZipArchiveInfo {
+  /** The size in bytes of the archive itself. Used by zipinfo. */
+  off64_t archive_size;
+  /** The number of entries in the archive. */
+  size_t entry_count;
+};
+
+/**
+ * Returns information about the given archive.
+ */
+ZipArchiveInfo GetArchiveInfo(ZipArchiveHandle archive);
+
 /*
- * Find an entry in the Zip archive, by name. |entryName| must be a null
- * terminated string, and |data| must point to a writeable memory location.
+ * Find an entry in the Zip archive, by name. |data| must be non-null.
  *
  * Returns 0 if an entry is found, and populates |data| with information
  * about this entry. Returns negative values otherwise.
@@ -164,7 +165,7 @@
  * On non-Windows platforms this method does not modify internal state and
  * can be called concurrently.
  */
-int32_t FindEntry(const ZipArchiveHandle archive, const ZipString& entryName, ZipEntry* data);
+int32_t FindEntry(const ZipArchiveHandle archive, const std::string_view entryName, ZipEntry* data);
 
 /*
  * Start iterating over all entries of a zip file. The order of iteration
@@ -180,7 +181,8 @@
  * Returns 0 on success and negative values on failure.
  */
 int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
-                       const ZipString* optional_prefix, const ZipString* optional_suffix);
+                       const std::string_view optional_prefix = "",
+                       const std::string_view optional_suffix = "");
 
 /*
  * Advance to the next element in the zipfile in iteration order.
@@ -188,7 +190,8 @@
  * Returns 0 on success, -1 if there are no more elements in this
  * archive and lower negative values on failure.
  */
-int32_t Next(void* cookie, ZipEntry* data, ZipString* name);
+int32_t Next(void* cookie, ZipEntry* data, std::string* name);
+int32_t Next(void* cookie, ZipEntry* data, std::string_view* name);
 
 /*
  * End iteration over all entries of a zip file and frees the memory allocated
diff --git a/libziparchive/include/ziparchive/zip_writer.h b/libziparchive/include/ziparchive/zip_writer.h
index f6c8427..d68683d 100644
--- a/libziparchive/include/ziparchive/zip_writer.h
+++ b/libziparchive/include/ziparchive/zip_writer.h
@@ -19,8 +19,10 @@
 #include <cstdio>
 #include <ctime>
 
+#include <gtest/gtest_prod.h>
 #include <memory>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "android-base/macros.h"
@@ -76,7 +78,7 @@
     uint32_t uncompressed_size;
     uint16_t last_mod_time;
     uint16_t last_mod_date;
-    uint32_t padding_length;
+    uint16_t padding_length;
     off64_t local_file_header_offset;
   };
 
@@ -101,7 +103,7 @@
    * Subsequent calls to WriteBytes(const void*, size_t) will add data to this entry.
    * Returns 0 on success, and an error value < 0 on failure.
    */
-  int32_t StartEntry(const char* path, size_t flags);
+  int32_t StartEntry(std::string_view path, size_t flags);
 
   /**
    * Starts a new zip entry with the given path and flags, where the
@@ -111,17 +113,17 @@
    * Subsequent calls to WriteBytes(const void*, size_t) will add data to this entry.
    * Returns 0 on success, and an error value < 0 on failure.
    */
-  int32_t StartAlignedEntry(const char* path, size_t flags, uint32_t alignment);
+  int32_t StartAlignedEntry(std::string_view path, size_t flags, uint32_t alignment);
 
   /**
    * Same as StartEntry(const char*, size_t), but sets a last modified time for the entry.
    */
-  int32_t StartEntryWithTime(const char* path, size_t flags, time_t time);
+  int32_t StartEntryWithTime(std::string_view path, size_t flags, time_t time);
 
   /**
    * Same as StartAlignedEntry(const char*, size_t), but sets a last modified time for the entry.
    */
-  int32_t StartAlignedEntryWithTime(const char* path, size_t flags, time_t time, uint32_t alignment);
+  int32_t StartAlignedEntryWithTime(std::string_view path, size_t flags, time_t time, uint32_t alignment);
 
   /**
    * Writes bytes to the zip file for the previously started zip entry.
@@ -161,9 +163,10 @@
 
   int32_t HandleError(int32_t error_code);
   int32_t PrepareDeflate();
-  int32_t StoreBytes(FileEntry* file, const void* data, size_t len);
-  int32_t CompressBytes(FileEntry* file, const void* data, size_t len);
+  int32_t StoreBytes(FileEntry* file, const void* data, uint32_t len);
+  int32_t CompressBytes(FileEntry* file, const void* data, uint32_t len);
   int32_t FlushCompressedBytes(FileEntry* file);
+  bool ShouldUseDataDescriptor() const;
 
   enum class State {
     kWritingZip,
@@ -181,4 +184,6 @@
 
   std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
   std::vector<uint8_t> buffer_;
+
+  FRIEND_TEST(zipwriter, WriteToUnseekableFile);
 };
diff --git a/libziparchive/libziparchive_fuzzer.cpp b/libziparchive/libziparchive_fuzzer.cpp
new file mode 100644
index 0000000..75e7939
--- /dev/null
+++ b/libziparchive/libziparchive_fuzzer.cpp
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <ziparchive/zip_archive.h>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  ZipArchiveHandle handle = nullptr;
+  OpenArchiveFromMemory(data, size, "fuzz", &handle);
+  CloseArchive(handle);
+  return 0;
+}
diff --git a/libziparchive/run-ziptool-tests-on-android.sh b/libziparchive/run-ziptool-tests-on-android.sh
new file mode 100755
index 0000000..3c23d43
--- /dev/null
+++ b/libziparchive/run-ziptool-tests-on-android.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# Copy the tests across.
+adb shell rm -rf /data/local/tmp/ziptool-tests/
+adb shell mkdir /data/local/tmp/ziptool-tests/
+adb push cli-tests/ /data/local/tmp/ziptool-tests/
+#adb push cli-test /data/local/tmp/ziptool-tests/
+
+if tty -s; then
+  dash_t="-t"
+else
+  dash_t=""
+fi
+
+exec adb shell $dash_t cli-test /data/local/tmp/ziptool-tests/cli-tests/*.test
diff --git a/libziparchive/testdata/empty.zip b/libziparchive/testdata/empty.zip
new file mode 100644
index 0000000..15cb0ec
--- /dev/null
+++ b/libziparchive/testdata/empty.zip
Binary files differ
diff --git a/libziparchive/testdata/zero-size-cd.zip b/libziparchive/testdata/zero-size-cd.zip
new file mode 100644
index 0000000..b6c8cbe
--- /dev/null
+++ b/libziparchive/testdata/zero-size-cd.zip
Binary files differ
diff --git a/libziparchive/unzip.cpp b/libziparchive/unzip.cpp
deleted file mode 100644
index 6756007..0000000
--- a/libziparchive/unzip.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (C) 2017 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 <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <set>
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/strings.h>
-#include <ziparchive/zip_archive.h>
-
-enum OverwriteMode {
-  kAlways,
-  kNever,
-  kPrompt,
-};
-
-static OverwriteMode overwrite_mode = kPrompt;
-static const char* flag_d = nullptr;
-static bool flag_l = false;
-static bool flag_p = false;
-static bool flag_q = false;
-static bool flag_v = false;
-static const char* archive_name = nullptr;
-static std::set<std::string> includes;
-static std::set<std::string> excludes;
-static uint64_t total_uncompressed_length = 0;
-static uint64_t total_compressed_length = 0;
-static size_t file_count = 0;
-
-static bool Filter(const std::string& name) {
-  if (!excludes.empty() && excludes.find(name) != excludes.end()) return true;
-  if (!includes.empty() && includes.find(name) == includes.end()) return true;
-  return false;
-}
-
-static bool MakeDirectoryHierarchy(const std::string& path) {
-  // stat rather than lstat because a symbolic link to a directory is fine too.
-  struct stat sb;
-  if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) return true;
-
-  // Ensure the parent directories exist first.
-  if (!MakeDirectoryHierarchy(android::base::Dirname(path))) return false;
-
-  // Then try to create this directory.
-  return (mkdir(path.c_str(), 0777) != -1);
-}
-
-static int CompressionRatio(int64_t uncompressed, int64_t compressed) {
-  if (uncompressed == 0) return 0;
-  return (100LL * (uncompressed - compressed)) / uncompressed;
-}
-
-static void MaybeShowHeader() {
-  if (!flag_q) printf("Archive:  %s\n", archive_name);
-  if (flag_v) {
-    printf(
-        " Length   Method    Size  Cmpr    Date    Time   CRC-32   Name\n"
-        "--------  ------  ------- ---- ---------- ----- --------  ----\n");
-  } else if (flag_l) {
-    printf(
-        "  Length      Date    Time    Name\n"
-        "---------  ---------- -----   ----\n");
-  }
-}
-
-static void MaybeShowFooter() {
-  if (flag_v) {
-    printf(
-        "--------          -------  ---                            -------\n"
-        "%8" PRId64 "         %8" PRId64 " %3d%%                            %zu file%s\n",
-        total_uncompressed_length, total_compressed_length,
-        CompressionRatio(total_uncompressed_length, total_compressed_length), file_count,
-        (file_count == 1) ? "" : "s");
-  } else if (flag_l) {
-    printf(
-        "---------                     -------\n"
-        "%9" PRId64 "                     %zu file%s\n",
-        total_uncompressed_length, file_count, (file_count == 1) ? "" : "s");
-  }
-}
-
-static bool PromptOverwrite(const std::string& dst) {
-  // TODO: [r]ename not implemented because it doesn't seem useful.
-  printf("replace %s? [y]es, [n]o, [A]ll, [N]one: ", dst.c_str());
-  fflush(stdout);
-  while (true) {
-    char* line = nullptr;
-    size_t n;
-    if (getline(&line, &n, stdin) == -1) {
-      error(1, 0, "(EOF/read error; assuming [N]one...)");
-      overwrite_mode = kNever;
-      return false;
-    }
-    if (n == 0) continue;
-    char cmd = line[0];
-    free(line);
-    switch (cmd) {
-      case 'y':
-        return true;
-      case 'n':
-        return false;
-      case 'A':
-        overwrite_mode = kAlways;
-        return true;
-      case 'N':
-        overwrite_mode = kNever;
-        return false;
-    }
-  }
-}
-
-static void ExtractToPipe(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
-  // We need to extract to memory because ExtractEntryToFile insists on
-  // being able to seek and truncate, and you can't do that with stdout.
-  uint8_t* buffer = new uint8_t[entry.uncompressed_length];
-  int err = ExtractToMemory(zah, &entry, buffer, entry.uncompressed_length);
-  if (err < 0) {
-    error(1, 0, "failed to extract %s: %s", name.c_str(), ErrorCodeString(err));
-  }
-  if (!android::base::WriteFully(1, buffer, entry.uncompressed_length)) {
-    error(1, errno, "failed to write %s to stdout", name.c_str());
-  }
-  delete[] buffer;
-}
-
-static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
-  // Bad filename?
-  if (android::base::StartsWith(name, "/") || android::base::StartsWith(name, "../") ||
-      name.find("/../") != std::string::npos) {
-    error(1, 0, "bad filename %s", name.c_str());
-  }
-
-  // Where are we actually extracting to (for human-readable output)?
-  std::string dst;
-  if (flag_d) {
-    dst = flag_d;
-    if (!android::base::EndsWith(dst, "/")) dst += '/';
-  }
-  dst += name;
-
-  // Ensure the directory hierarchy exists.
-  if (!MakeDirectoryHierarchy(android::base::Dirname(name))) {
-    error(1, errno, "couldn't create directory hierarchy for %s", dst.c_str());
-  }
-
-  // An entry in a zip file can just be a directory itself.
-  if (android::base::EndsWith(name, "/")) {
-    if (mkdir(name.c_str(), entry.unix_mode) == -1) {
-      // If the directory already exists, that's fine.
-      if (errno == EEXIST) {
-        struct stat sb;
-        if (stat(name.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) return;
-      }
-      error(1, errno, "couldn't extract directory %s", dst.c_str());
-    }
-    return;
-  }
-
-  // Create the file.
-  int fd = open(name.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC | O_EXCL, entry.unix_mode);
-  if (fd == -1 && errno == EEXIST) {
-    if (overwrite_mode == kNever) return;
-    if (overwrite_mode == kPrompt && !PromptOverwrite(dst)) return;
-    // Either overwrite_mode is kAlways or the user consented to this specific case.
-    fd = open(name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, entry.unix_mode);
-  }
-  if (fd == -1) error(1, errno, "couldn't create file %s", dst.c_str());
-
-  // Actually extract into the file.
-  if (!flag_q) printf("  inflating: %s\n", dst.c_str());
-  int err = ExtractEntryToFile(zah, &entry, fd);
-  if (err < 0) error(1, 0, "failed to extract %s: %s", dst.c_str(), ErrorCodeString(err));
-  close(fd);
-}
-
-static void ListOne(const ZipEntry& entry, const std::string& name) {
-  tm t = entry.GetModificationTime();
-  char time[32];
-  snprintf(time, sizeof(time), "%04d-%02d-%02d %02d:%02d", t.tm_year + 1900, t.tm_mon + 1,
-           t.tm_mday, t.tm_hour, t.tm_min);
-  if (flag_v) {
-    printf("%8d  %s  %7d %3d%% %s %08x  %s\n", entry.uncompressed_length,
-           (entry.method == kCompressStored) ? "Stored" : "Defl:N", entry.compressed_length,
-           CompressionRatio(entry.uncompressed_length, entry.compressed_length), time, entry.crc32,
-           name.c_str());
-  } else {
-    printf("%9d  %s   %s\n", entry.uncompressed_length, time, name.c_str());
-  }
-}
-
-static void ProcessOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
-  if (flag_l || flag_v) {
-    // -l or -lv or -lq or -v.
-    ListOne(entry, name);
-  } else {
-    // Actually extract.
-    if (flag_p) {
-      ExtractToPipe(zah, entry, name);
-    } else {
-      ExtractOne(zah, entry, name);
-    }
-  }
-  total_uncompressed_length += entry.uncompressed_length;
-  total_compressed_length += entry.compressed_length;
-  ++file_count;
-}
-
-static void ProcessAll(ZipArchiveHandle zah) {
-  MaybeShowHeader();
-
-  // libziparchive iteration order doesn't match the central directory.
-  // We could sort, but that would cost extra and wouldn't match either.
-  void* cookie;
-  int err = StartIteration(zah, &cookie, nullptr, nullptr);
-  if (err != 0) {
-    error(1, 0, "couldn't iterate %s: %s", archive_name, ErrorCodeString(err));
-  }
-
-  ZipEntry entry;
-  ZipString string;
-  while ((err = Next(cookie, &entry, &string)) >= 0) {
-    std::string name(string.name, string.name + string.name_length);
-    if (!Filter(name)) ProcessOne(zah, entry, name);
-  }
-
-  if (err < -1) error(1, 0, "failed iterating %s: %s", archive_name, ErrorCodeString(err));
-  EndIteration(cookie);
-
-  MaybeShowFooter();
-}
-
-static void ShowHelp(bool full) {
-  fprintf(full ? stdout : stderr, "usage: unzip [-d DIR] [-lnopqv] ZIP [FILE...] [-x FILE...]\n");
-  if (!full) exit(EXIT_FAILURE);
-
-  printf(
-      "\n"
-      "Extract FILEs from ZIP archive. Default is all files.\n"
-      "\n"
-      "-d DIR	Extract into DIR\n"
-      "-l	List contents (-lq excludes archive name, -lv is verbose)\n"
-      "-n	Never overwrite files (default: prompt)\n"
-      "-o	Always overwrite files\n"
-      "-p	Pipe to stdout\n"
-      "-q	Quiet\n"
-      "-v	List contents verbosely\n"
-      "-x FILE	Exclude files\n");
-  exit(EXIT_SUCCESS);
-}
-
-int main(int argc, char* argv[]) {
-  static struct option opts[] = {
-      {"help", no_argument, 0, 'h'},
-  };
-  bool saw_x = false;
-  int opt;
-  while ((opt = getopt_long(argc, argv, "-d:hlnopqvx", opts, nullptr)) != -1) {
-    switch (opt) {
-      case 'd':
-        flag_d = optarg;
-        break;
-      case 'h':
-        ShowHelp(true);
-        break;
-      case 'l':
-        flag_l = true;
-        break;
-      case 'n':
-        overwrite_mode = kNever;
-        break;
-      case 'o':
-        overwrite_mode = kAlways;
-        break;
-      case 'p':
-        flag_p = flag_q = true;
-        break;
-      case 'q':
-        flag_q = true;
-        break;
-      case 'v':
-        flag_v = true;
-        break;
-      case 'x':
-        saw_x = true;
-        break;
-      case 1:
-        // -x swallows all following arguments, so we use '-' in the getopt
-        // string and collect files here.
-        if (!archive_name) {
-          archive_name = optarg;
-        } else if (saw_x) {
-          excludes.insert(optarg);
-        } else {
-          includes.insert(optarg);
-        }
-        break;
-      default:
-        ShowHelp(false);
-    }
-  }
-
-  if (!archive_name) error(1, 0, "missing archive filename");
-
-  // We can't support "-" to unzip from stdin because libziparchive relies on mmap.
-  ZipArchiveHandle zah;
-  int32_t err;
-  if ((err = OpenArchive(archive_name, &zah)) != 0) {
-    error(1, 0, "couldn't open %s: %s", archive_name, ErrorCodeString(err));
-  }
-
-  // Implement -d by changing into that directory.
-  // We'll create implicit directories based on paths in the zip file, but we
-  // require that the -d directory already exists.
-  if (flag_d && chdir(flag_d) == -1) error(1, errno, "couldn't chdir to %s", flag_d);
-
-  ProcessAll(zah);
-
-  CloseArchive(zah);
-  return 0;
-}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 0710d0a..68837cc 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -47,6 +47,7 @@
 #include <android-base/macros.h>  // TEMP_FAILURE_RETRY may or may not be in unistd
 #include <android-base/mapped_file.h>
 #include <android-base/memory.h>
+#include <android-base/strings.h>
 #include <android-base/utf8.h>
 #include <log/log.h>
 #include "zlib.h"
@@ -101,38 +102,8 @@
   return val;
 }
 
-static uint32_t ComputeHash(const ZipString& name) {
-#if !defined(_WIN32)
-  return std::hash<std::string_view>{}(
-      std::string_view(reinterpret_cast<const char*>(name.name), name.name_length));
-#else
-  // Remove this code path once the windows compiler knows how to compile the above statement.
-  uint32_t hash = 0;
-  uint16_t len = name.name_length;
-  const uint8_t* str = name.name;
-
-  while (len--) {
-    hash = hash * 31 + *str++;
-  }
-
-  return hash;
-#endif
-}
-
-static bool isZipStringEqual(const uint8_t* start, const ZipString& zip_string,
-                             const ZipStringOffset& zip_string_offset) {
-  const ZipString from_offset = zip_string_offset.GetZipString(start);
-  return from_offset == zip_string;
-}
-
-/**
- * Returns offset of ZipString#name from the start of the central directory in the memory map.
- * For valid ZipStrings contained in the zip archive mmap, 0 < offset < 0xffffff.
- */
-static inline uint32_t GetOffset(const uint8_t* name, const uint8_t* start) {
-  CHECK_GT(name, start);
-  CHECK_LT(name, start + 0xffffff);
-  return static_cast<uint32_t>(name - start);
+static uint32_t ComputeHash(std::string_view name) {
+  return static_cast<uint32_t>(std::hash<std::string_view>{}(name));
 }
 
 /*
@@ -140,27 +111,27 @@
  * valid range.
  */
 static int64_t EntryToIndex(const ZipStringOffset* hash_table, const uint32_t hash_table_size,
-                            const ZipString& name, const uint8_t* start) {
+                            std::string_view name, const uint8_t* start) {
   const uint32_t hash = ComputeHash(name);
 
   // NOTE: (hash_table_size - 1) is guaranteed to be non-negative.
   uint32_t ent = hash & (hash_table_size - 1);
   while (hash_table[ent].name_offset != 0) {
-    if (isZipStringEqual(start, name, hash_table[ent])) {
+    if (hash_table[ent].ToStringView(start) == name) {
       return ent;
     }
     ent = (ent + 1) & (hash_table_size - 1);
   }
 
-  ALOGV("Zip: Unable to find entry %.*s", name.name_length, name.name);
+  ALOGV("Zip: Unable to find entry %.*s", static_cast<int>(name.size()), name.data());
   return kEntryNotFound;
 }
 
 /*
  * Add a new entry to the hash table.
  */
-static int32_t AddToHash(ZipStringOffset* hash_table, const uint64_t hash_table_size,
-                         const ZipString& name, const uint8_t* start) {
+static int32_t AddToHash(ZipStringOffset* hash_table, const uint32_t hash_table_size,
+                         std::string_view name, const uint8_t* start) {
   const uint64_t hash = ComputeHash(name);
   uint32_t ent = hash & (hash_table_size - 1);
 
@@ -169,15 +140,18 @@
    * Further, we guarantee that the hashtable size is not 0.
    */
   while (hash_table[ent].name_offset != 0) {
-    if (isZipStringEqual(start, name, hash_table[ent])) {
-      // We've found a duplicate entry. We don't accept it
-      ALOGW("Zip: Found duplicate entry %.*s", name.name_length, name.name);
+    if (hash_table[ent].ToStringView(start) == name) {
+      // We've found a duplicate entry. We don't accept duplicates.
+      ALOGW("Zip: Found duplicate entry %.*s", static_cast<int>(name.size()), name.data());
       return kDuplicateEntry;
     }
     ent = (ent + 1) & (hash_table_size - 1);
   }
-  hash_table[ent].name_offset = GetOffset(name.name, start);
-  hash_table[ent].name_length = name.name_length;
+
+  // `name` has already been validated before entry.
+  const char* start_char = reinterpret_cast<const char*>(start);
+  hash_table[ent].name_offset = static_cast<uint32_t>(name.data() - start_char);
+  hash_table[ent].name_length = static_cast<uint16_t>(name.size());
   return 0;
 }
 
@@ -204,7 +178,7 @@
 #endif
 }
 
-ZipArchive::ZipArchive(void* address, size_t length)
+ZipArchive::ZipArchive(const void* address, size_t length)
     : mapped_zip(address, length),
       close_file(false),
       directory_offset(0),
@@ -227,7 +201,7 @@
 }
 
 static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* archive,
-                                    off64_t file_length, off64_t read_amount,
+                                    off64_t file_length, uint32_t read_amount,
                                     uint8_t* scan_buffer) {
   const off64_t search_start = file_length - read_amount;
 
@@ -243,7 +217,8 @@
    * doing an initial minimal read; if we don't find it, retry with a
    * second read as above.)
    */
-  int i = read_amount - sizeof(EocdRecord);
+  CHECK_LE(read_amount, std::numeric_limits<int32_t>::max());
+  int32_t i = read_amount - sizeof(EocdRecord);
   for (; i >= 0; i--) {
     if (scan_buffer[i] == 0x50) {
       uint32_t* sig_addr = reinterpret_cast<uint32_t*>(&scan_buffer[i]);
@@ -290,14 +265,10 @@
   ALOGV("+++ num_entries=%" PRIu32 " dir_size=%" PRIu32 " dir_offset=%" PRIu32, eocd->num_records,
         eocd->cd_size, eocd->cd_start_offset);
 
-  /*
-   * It all looks good.  Create a mapping for the CD, and set the fields
-   * in archive.
-   */
-
+  // It all looks good.  Create a mapping for the CD, and set the fields
+  // in archive.
   if (!archive->InitializeCentralDirectory(static_cast<off64_t>(eocd->cd_start_offset),
                                            static_cast<size_t>(eocd->cd_size))) {
-    ALOGE("Zip: failed to intialize central directory.\n");
     return kMmapFailed;
   }
 
@@ -346,9 +317,9 @@
    *
    * We start by pulling in the last part of the file.
    */
-  off64_t read_amount = kMaxEOCDSearch;
+  uint32_t read_amount = kMaxEOCDSearch;
   if (file_length < read_amount) {
-    read_amount = file_length;
+    read_amount = static_cast<uint32_t>(file_length);
   }
 
   std::vector<uint8_t> scan_buffer(read_amount);
@@ -378,8 +349,8 @@
       reinterpret_cast<ZipStringOffset*>(calloc(archive->hash_table_size, sizeof(ZipStringOffset)));
   if (archive->hash_table == nullptr) {
     ALOGW("Zip: unable to allocate the %u-entry hash_table, entry size: %zu",
-          archive->hash_table_size, sizeof(ZipString));
-    return -1;
+          archive->hash_table_size, sizeof(ZipStringOffset));
+    return kAllocationFailed;
   }
 
   /*
@@ -390,24 +361,25 @@
   const uint8_t* ptr = cd_ptr;
   for (uint16_t i = 0; i < num_entries; i++) {
     if (ptr > cd_end - sizeof(CentralDirectoryRecord)) {
-      ALOGW("Zip: ran off the end (at %" PRIu16 ")", i);
+      ALOGW("Zip: ran off the end (item #%" PRIu16 ", %zu bytes of central directory)", i,
+            cd_length);
 #if defined(__ANDROID__)
       android_errorWriteLog(0x534e4554, "36392138");
 #endif
-      return -1;
+      return kInvalidFile;
     }
 
     const CentralDirectoryRecord* cdr = reinterpret_cast<const CentralDirectoryRecord*>(ptr);
     if (cdr->record_signature != CentralDirectoryRecord::kSignature) {
       ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i);
-      return -1;
+      return kInvalidFile;
     }
 
     const off64_t local_header_offset = cdr->local_file_header_offset;
     if (local_header_offset >= archive->directory_offset) {
       ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16,
             static_cast<int64_t>(local_header_offset), i);
-      return -1;
+      return kInvalidFile;
     }
 
     const uint16_t file_name_length = cdr->file_name_length;
@@ -416,21 +388,19 @@
     const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
 
     if (file_name + file_name_length > cd_end) {
-      ALOGW(
-          "Zip: file name boundary exceeds the central directory range, file_name_length: "
-          "%" PRIx16 ", cd_length: %zu",
-          file_name_length, cd_length);
-      return -1;
+      ALOGW("Zip: file name for entry %" PRIu16
+            " exceeds the central directory range, file_name_length: %" PRIu16 ", cd_length: %zu",
+            i, file_name_length, cd_length);
+      return kInvalidEntryName;
     }
-    /* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */
+    // Check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters.
     if (!IsValidEntryName(file_name, file_name_length)) {
-      return -1;
+      ALOGW("Zip: invalid file name at entry %" PRIu16, i);
+      return kInvalidEntryName;
     }
 
-    /* add the CDE filename to the hash table */
-    ZipString entry_name;
-    entry_name.name = file_name;
-    entry_name.name_length = file_name_length;
+    // Add the CDE filename to the hash table.
+    std::string_view entry_name{reinterpret_cast<const char*>(file_name), file_name_length};
     const int add_result = AddToHash(archive->hash_table, archive->hash_table_size, entry_name,
                                      archive->central_directory.GetBasePtr());
     if (add_result != 0) {
@@ -441,7 +411,7 @@
     ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length;
     if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) {
       ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16, ptr - cd_ptr, cd_length, i);
-      return -1;
+      return kInvalidFile;
     }
   }
 
@@ -449,7 +419,7 @@
   if (!archive->mapped_zip.ReadAtOffset(reinterpret_cast<uint8_t*>(&lfh_start_bytes),
                                         sizeof(uint32_t), 0)) {
     ALOGW("Zip: Unable to read header for entry at offset == 0.");
-    return -1;
+    return kInvalidFile;
   }
 
   if (lfh_start_bytes != LocalFileHeader::kSignature) {
@@ -457,7 +427,7 @@
 #if defined(__ANDROID__)
     android_errorWriteLog(0x534e4554, "64211847");
 #endif
-    return -1;
+    return kInvalidFile;
   }
 
   ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);
@@ -466,16 +436,8 @@
 }
 
 static int32_t OpenArchiveInternal(ZipArchive* archive, const char* debug_file_name) {
-  int32_t result = -1;
-  if ((result = MapCentralDirectory(debug_file_name, archive)) != 0) {
-    return result;
-  }
-
-  if ((result = ParseZipArchive(archive))) {
-    return result;
-  }
-
-  return 0;
+  int32_t result = MapCentralDirectory(debug_file_name, archive);
+  return result != 0 ? result : ParseZipArchive(archive);
 }
 
 int32_t OpenArchiveFd(int fd, const char* debug_file_name, ZipArchiveHandle* handle,
@@ -498,13 +460,20 @@
   return OpenArchiveInternal(archive, fileName);
 }
 
-int32_t OpenArchiveFromMemory(void* address, size_t length, const char* debug_file_name,
+int32_t OpenArchiveFromMemory(const void* address, size_t length, const char* debug_file_name,
                               ZipArchiveHandle* handle) {
   ZipArchive* archive = new ZipArchive(address, length);
   *handle = archive;
   return OpenArchiveInternal(archive, debug_file_name);
 }
 
+ZipArchiveInfo GetArchiveInfo(ZipArchiveHandle archive) {
+  ZipArchiveInfo result;
+  result.archive_size = archive->mapped_zip.GetFileLength();
+  result.entry_count = archive->num_entries;
+  return result;
+}
+
 /*
  * Close a ZipArchive, closing the file and freeing the contents.
  */
@@ -545,21 +514,19 @@
   return 0;
 }
 
-static int32_t FindEntry(const ZipArchive* archive, const int ent, ZipEntry* data) {
+static int32_t FindEntry(const ZipArchive* archive, const int32_t ent, ZipEntry* data) {
   const uint16_t nameLen = archive->hash_table[ent].name_length;
 
   // Recover the start of the central directory entry from the filename
   // pointer.  The filename is the first entry past the fixed-size data,
   // so we can just subtract back from that.
-  const ZipString from_offset =
-      archive->hash_table[ent].GetZipString(archive->central_directory.GetBasePtr());
-  const uint8_t* ptr = from_offset.name;
+  const uint8_t* base_ptr = archive->central_directory.GetBasePtr();
+  const uint8_t* ptr = base_ptr + archive->hash_table[ent].name_offset;
   ptr -= sizeof(CentralDirectoryRecord);
 
   // This is the base of our mmapped region, we have to sanity check that
   // the name that's in the hash table is a pointer to a location within
   // this mapped region.
-  const uint8_t* base_ptr = archive->central_directory.GetBasePtr();
   if (ptr < base_ptr || ptr > base_ptr + archive->central_directory.GetMapLength()) {
     ALOGW("Zip: Invalid entry pointer");
     return kInvalidOffset;
@@ -643,34 +610,41 @@
   }
 
   // 4.4.2.1: the upper byte of `version_made_by` gives the source OS. Unix is 3.
-  if ((cdr->version_made_by >> 8) == 3) {
+  data->version_made_by = cdr->version_made_by;
+  data->external_file_attributes = cdr->external_file_attributes;
+  if ((data->version_made_by >> 8) == 3) {
     data->unix_mode = (cdr->external_file_attributes >> 16) & 0xffff;
   } else {
     data->unix_mode = 0777;
   }
 
+  // 4.4.4: general purpose bit flags.
+  data->gpbf = lfh->gpb_flags;
+
+  // 4.4.14: the lowest bit of the internal file attributes field indicates text.
+  // Currently only needed to implement zipinfo.
+  data->is_text = (cdr->internal_file_attributes & 1);
+
   // Check that the local file header name matches the declared
   // name in the central directory.
-  if (lfh->file_name_length == nameLen) {
-    const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader);
-    if (name_offset + lfh->file_name_length > cd_offset) {
-      ALOGW("Zip: Invalid declared length");
-      return kInvalidOffset;
-    }
-
-    std::vector<uint8_t> name_buf(nameLen);
-    if (!archive->mapped_zip.ReadAtOffset(name_buf.data(), nameLen, name_offset)) {
-      ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
-      return kIoError;
-    }
-    const ZipString from_offset =
-        archive->hash_table[ent].GetZipString(archive->central_directory.GetBasePtr());
-    if (memcmp(from_offset.name, name_buf.data(), nameLen)) {
-      return kInconsistentInformation;
-    }
-
-  } else {
-    ALOGW("Zip: lfh name did not match central directory.");
+  if (lfh->file_name_length != nameLen) {
+    ALOGW("Zip: lfh name length did not match central directory");
+    return kInconsistentInformation;
+  }
+  const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader);
+  if (name_offset + lfh->file_name_length > cd_offset) {
+    ALOGW("Zip: lfh name has invalid declared length");
+    return kInvalidOffset;
+  }
+  std::vector<uint8_t> name_buf(nameLen);
+  if (!archive->mapped_zip.ReadAtOffset(name_buf.data(), nameLen, name_offset)) {
+    ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
+    return kIoError;
+  }
+  const std::string_view entry_name =
+      archive->hash_table[ent].ToStringView(archive->central_directory.GetBasePtr());
+  if (memcmp(entry_name.data(), name_buf.data(), nameLen) != 0) {
+    ALOGW("Zip: lfh name did not match central directory");
     return kInconsistentInformation;
   }
 
@@ -701,52 +675,32 @@
 }
 
 struct IterationHandle {
-  uint32_t position;
-  // We're not using vector here because this code is used in the Windows SDK
-  // where the STL is not available.
-  ZipString prefix;
-  ZipString suffix;
   ZipArchive* archive;
 
-  IterationHandle(const ZipString* in_prefix, const ZipString* in_suffix) {
-    if (in_prefix) {
-      uint8_t* name_copy = new uint8_t[in_prefix->name_length];
-      memcpy(name_copy, in_prefix->name, in_prefix->name_length);
-      prefix.name = name_copy;
-      prefix.name_length = in_prefix->name_length;
-    } else {
-      prefix.name = NULL;
-      prefix.name_length = 0;
-    }
-    if (in_suffix) {
-      uint8_t* name_copy = new uint8_t[in_suffix->name_length];
-      memcpy(name_copy, in_suffix->name, in_suffix->name_length);
-      suffix.name = name_copy;
-      suffix.name_length = in_suffix->name_length;
-    } else {
-      suffix.name = NULL;
-      suffix.name_length = 0;
-    }
-  }
+  std::string prefix;
+  std::string suffix;
 
-  ~IterationHandle() {
-    delete[] prefix.name;
-    delete[] suffix.name;
-  }
+  uint32_t position = 0;
+
+  IterationHandle(ZipArchive* archive, std::string_view in_prefix, std::string_view in_suffix)
+      : archive(archive), prefix(in_prefix), suffix(in_suffix) {}
 };
 
 int32_t StartIteration(ZipArchiveHandle archive, void** cookie_ptr,
-                       const ZipString* optional_prefix, const ZipString* optional_suffix) {
+                       const std::string_view optional_prefix,
+                       const std::string_view optional_suffix) {
   if (archive == NULL || archive->hash_table == NULL) {
     ALOGW("Zip: Invalid ZipArchiveHandle");
     return kInvalidHandle;
   }
 
-  IterationHandle* cookie = new IterationHandle(optional_prefix, optional_suffix);
-  cookie->position = 0;
-  cookie->archive = archive;
+  if (optional_prefix.size() > static_cast<size_t>(UINT16_MAX) ||
+      optional_suffix.size() > static_cast<size_t>(UINT16_MAX)) {
+    ALOGW("Zip: prefix/suffix too long");
+    return kInvalidEntryName;
+  }
 
-  *cookie_ptr = cookie;
+  *cookie_ptr = new IterationHandle(archive, optional_prefix, optional_suffix);
   return 0;
 }
 
@@ -754,22 +708,33 @@
   delete reinterpret_cast<IterationHandle*>(cookie);
 }
 
-int32_t FindEntry(const ZipArchiveHandle archive, const ZipString& entryName, ZipEntry* data) {
-  if (entryName.name_length == 0) {
-    ALOGW("Zip: Invalid filename %.*s", entryName.name_length, entryName.name);
+int32_t FindEntry(const ZipArchiveHandle archive, const std::string_view entryName,
+                  ZipEntry* data) {
+  if (entryName.empty() || entryName.size() > static_cast<size_t>(UINT16_MAX)) {
+    ALOGW("Zip: Invalid filename of length %zu", entryName.size());
     return kInvalidEntryName;
   }
 
   const int64_t ent = EntryToIndex(archive->hash_table, archive->hash_table_size, entryName,
                                    archive->central_directory.GetBasePtr());
   if (ent < 0) {
-    ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
-    return ent;
+    ALOGV("Zip: Could not find entry %.*s", static_cast<int>(entryName.size()), entryName.data());
+    return static_cast<int32_t>(ent);  // kEntryNotFound is safe to truncate.
   }
-  return FindEntry(archive, ent, data);
+  // We know there are at most hash_table_size entries, safe to truncate.
+  return FindEntry(archive, static_cast<uint32_t>(ent), data);
 }
 
-int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
+int32_t Next(void* cookie, ZipEntry* data, std::string* name) {
+  std::string_view sv;
+  int32_t result = Next(cookie, data, &sv);
+  if (result == 0 && name) {
+    *name = std::string(sv);
+  }
+  return result;
+}
+
+int32_t Next(void* cookie, ZipEntry* data, std::string_view* name) {
   IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
   if (handle == NULL) {
     ALOGW("Zip: Null ZipArchiveHandle");
@@ -786,16 +751,14 @@
   const uint32_t hash_table_length = archive->hash_table_size;
   const ZipStringOffset* hash_table = archive->hash_table;
   for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
-    const ZipString from_offset =
-        hash_table[i].GetZipString(archive->central_directory.GetBasePtr());
-    if (hash_table[i].name_offset != 0 &&
-        (handle->prefix.name_length == 0 || from_offset.StartsWith(handle->prefix)) &&
-        (handle->suffix.name_length == 0 || from_offset.EndsWith(handle->suffix))) {
+    const std::string_view entry_name =
+        hash_table[i].ToStringView(archive->central_directory.GetBasePtr());
+    if (hash_table[i].name_offset != 0 && (android::base::StartsWith(entry_name, handle->prefix) &&
+                                           android::base::EndsWith(entry_name, handle->suffix))) {
       handle->position = (i + 1);
       const int error = FindEntry(archive, i, data);
-      if (!error) {
-        name->name = from_offset.name;
-        name->name_length = hash_table[i].name_length;
+      if (!error && name) {
+        *name = entry_name;
       }
       return error;
     }
@@ -849,7 +812,6 @@
       return FileWriter{};
     }
 
-    int result = 0;
 #if defined(__linux__)
     if (declared_length > 0) {
       // Make sure we have enough space on the volume to extract the compressed
@@ -861,7 +823,7 @@
       // EOPNOTSUPP error when issued in other filesystems.
       // Hence, check for the return error code before concluding that the
       // disk does not have enough space.
-      result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
+      long result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
       if (result == -1 && errno == ENOSPC) {
         ALOGW("Zip: unable to allocate %" PRId64 " bytes at offset %" PRId64 ": %s",
               static_cast<int64_t>(declared_length), static_cast<int64_t>(current_offset),
@@ -879,7 +841,7 @@
 
     // Block device doesn't support ftruncate(2).
     if (!S_ISBLK(sb.st_mode)) {
-      result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+      long result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
       if (result == -1) {
         ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
               static_cast<int64_t>(declared_length + current_offset), strerror(errno));
@@ -998,16 +960,16 @@
   std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
 
   const bool compute_crc = (crc_out != nullptr);
-  uint64_t crc = 0;
+  uLong crc = 0;
   uint32_t remaining_bytes = compressed_length;
   do {
     /* read as much as we can */
     if (zstream.avail_in == 0) {
-      const size_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
+      const uint32_t read_size = (remaining_bytes > kBufSize) ? kBufSize : remaining_bytes;
       const uint32_t offset = (compressed_length - remaining_bytes);
       // Make sure to read at offset to ensure concurrent access to the fd.
       if (!reader.ReadAtOffset(read_buf.data(), read_size, offset)) {
-        ALOGW("Zip: inflate read failed, getSize = %zu: %s", read_size, strerror(errno));
+        ALOGW("Zip: inflate read failed, getSize = %u: %s", read_size, strerror(errno));
         return kIoError;
       }
 
@@ -1031,7 +993,8 @@
       if (!writer->Append(&write_buf[0], write_size)) {
         return kIoError;
       } else if (compute_crc) {
-        crc = crc32(crc, &write_buf[0], write_size);
+        DCHECK_LE(write_size, kBufSize);
+        crc = crc32(crc, &write_buf[0], static_cast<uint32_t>(write_size));
       }
 
       zstream.next_out = &write_buf[0];
@@ -1076,17 +1039,17 @@
 
   const uint32_t length = entry->uncompressed_length;
   uint32_t count = 0;
-  uint64_t crc = 0;
+  uLong crc = 0;
   while (count < length) {
     uint32_t remaining = length - count;
     off64_t offset = entry->offset + count;
 
     // Safe conversion because kBufSize is narrow enough for a 32 bit signed value.
-    const size_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
+    const uint32_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
 
     // Make sure to read at offset to ensure concurrent access to the fd.
     if (!mapped_zip.ReadAtOffset(buf.data(), block_size, offset)) {
-      ALOGW("CopyFileToFile: copy read failed, block_size = %zu, offset = %" PRId64 ": %s",
+      ALOGW("CopyFileToFile: copy read failed, block_size = %u, offset = %" PRId64 ": %s",
             block_size, static_cast<int64_t>(offset), strerror(errno));
       return kIoError;
     }
@@ -1163,12 +1126,6 @@
   return archive->mapped_zip.GetFileDescriptor();
 }
 
-ZipString::ZipString(const char* entry_name) : name(reinterpret_cast<const uint8_t*>(entry_name)) {
-  size_t len = strlen(entry_name);
-  CHECK_LE(len, static_cast<size_t>(UINT16_MAX));
-  name_length = static_cast<uint16_t>(len);
-}
-
 #if !defined(_WIN32)
 class ProcessWriter : public zip_archive::Writer {
  public:
@@ -1200,7 +1157,7 @@
   return fd_;
 }
 
-void* MappedZipFile::GetBasePtr() const {
+const void* MappedZipFile::GetBasePtr() const {
   if (has_fd_) {
     ALOGW("Zip: MappedZipFile doesn't have a base pointer.");
     return nullptr;
@@ -1217,7 +1174,7 @@
     return result;
   } else {
     if (base_ptr_ == nullptr) {
-      ALOGE("Zip: invalid file map\n");
+      ALOGE("Zip: invalid file map");
       return -1;
     }
     return static_cast<off64_t>(data_length_);
@@ -1228,21 +1185,22 @@
 bool MappedZipFile::ReadAtOffset(uint8_t* buf, size_t len, off64_t off) const {
   if (has_fd_) {
     if (!android::base::ReadFullyAtOffset(fd_, buf, len, off)) {
-      ALOGE("Zip: failed to read at offset %" PRId64 "\n", off);
+      ALOGE("Zip: failed to read at offset %" PRId64, off);
       return false;
     }
   } else {
     if (off < 0 || off > static_cast<off64_t>(data_length_)) {
-      ALOGE("Zip: invalid offset: %" PRId64 ", data length: %" PRId64 "\n", off, data_length_);
+      ALOGE("Zip: invalid offset: %" PRId64 ", data length: %" PRId64, off, data_length_);
       return false;
     }
-    memcpy(buf, static_cast<uint8_t*>(base_ptr_) + off, len);
+    memcpy(buf, static_cast<const uint8_t*>(base_ptr_) + off, len);
   }
   return true;
 }
 
-void CentralDirectory::Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size) {
-  base_ptr_ = static_cast<uint8_t*>(map_base_ptr) + cd_start_offset;
+void CentralDirectory::Initialize(const void* map_base_ptr, off64_t cd_start_offset,
+                                  size_t cd_size) {
+  base_ptr_ = static_cast<const uint8_t*>(map_base_ptr) + cd_start_offset;
   length_ = cd_size;
 }
 
@@ -1250,13 +1208,17 @@
   if (mapped_zip.HasFd()) {
     directory_map = android::base::MappedFile::FromFd(mapped_zip.GetFileDescriptor(),
                                                       cd_start_offset, cd_size, PROT_READ);
-    if (!directory_map) return false;
+    if (!directory_map) {
+      ALOGE("Zip: failed to map central directory (offset %" PRId64 ", size %zu): %s",
+            cd_start_offset, cd_size, strerror(errno));
+      return false;
+    }
 
     CHECK_EQ(directory_map->size(), cd_size);
     central_directory.Initialize(directory_map->data(), 0 /*offset*/, cd_size);
   } else {
     if (mapped_zip.GetBasePtr() == nullptr) {
-      ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer\n");
+      ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer");
       return false;
     }
     if (static_cast<off64_t>(cd_start_offset) + static_cast<off64_t>(cd_size) >
diff --git a/libziparchive/zip_archive_benchmark.cpp b/libziparchive/zip_archive_benchmark.cpp
index 46aa5a6..09d3b8a 100644
--- a/libziparchive/zip_archive_benchmark.cpp
+++ b/libziparchive/zip_archive_benchmark.cpp
@@ -55,10 +55,10 @@
 
   // In order to walk through all file names in the archive, look for a name
   // that does not exist in the archive.
-  ZipString name("thisFileNameDoesNotExist");
+  std::string_view name("thisFileNameDoesNotExist");
 
   // Start the benchmark.
-  while (state.KeepRunning()) {
+  for (auto _ : state) {
     OpenArchive(temp_file->path, &handle);
     FindEntry(handle, name, &data);
     CloseArchive(handle);
@@ -71,11 +71,11 @@
   ZipArchiveHandle handle;
   void* iteration_cookie;
   ZipEntry data;
-  ZipString name;
+  std::string name;
 
-  while (state.KeepRunning()) {
+  for (auto _ : state) {
     OpenArchive(temp_file->path, &handle);
-    StartIteration(handle, &iteration_cookie, nullptr, nullptr);
+    StartIteration(handle, &iteration_cookie);
     while (Next(iteration_cookie, &data, &name) == 0) {
     }
     EndIteration(iteration_cookie);
@@ -84,4 +84,27 @@
 }
 BENCHMARK(Iterate_all_files);
 
+static void StartAlignedEntry(benchmark::State& state) {
+  TemporaryFile file;
+  FILE* fp = fdopen(file.fd, "w");
+
+  ZipWriter writer(fp);
+
+  auto alignment = uint32_t(state.range(0));
+  std::string name = "name";
+  int counter = 0;
+  for (auto _ : state) {
+    writer.StartAlignedEntry(name + std::to_string(counter++), 0, alignment);
+    state.PauseTiming();
+    writer.WriteBytes("hola", 4);
+    writer.FinishEntry();
+    state.ResumeTiming();
+  }
+
+  writer.Finish();
+  fclose(fp);
+}
+BENCHMARK(StartAlignedEntry)->Arg(2)->Arg(16)->Arg(1024)->Arg(4096);
+
+
 BENCHMARK_MAIN();
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 330a02a..1d05fc7 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -42,6 +42,7 @@
     "Invalid entry name",
     "I/O error",
     "File mapping failed",
+    "Allocation failed",
 };
 
 enum ErrorCodes : int32_t {
@@ -87,7 +88,10 @@
   // We were not able to mmap the central directory or entry contents.
   kMmapFailed = -12,
 
-  kLastErrorCode = kMmapFailed,
+  // An allocation failed.
+  kAllocationFailed = -13,
+
+  kLastErrorCode = kAllocationFailed,
 };
 
 class MappedZipFile {
@@ -95,14 +99,14 @@
   explicit MappedZipFile(const int fd)
       : has_fd_(true), fd_(fd), base_ptr_(nullptr), data_length_(0) {}
 
-  explicit MappedZipFile(void* address, size_t length)
+  explicit MappedZipFile(const void* address, size_t length)
       : has_fd_(false), fd_(-1), base_ptr_(address), data_length_(static_cast<off64_t>(length)) {}
 
   bool HasFd() const { return has_fd_; }
 
   int GetFileDescriptor() const;
 
-  void* GetBasePtr() const;
+  const void* GetBasePtr() const;
 
   off64_t GetFileLength() const;
 
@@ -117,7 +121,7 @@
 
   const int fd_;
 
-  void* const base_ptr_;
+  const void* const base_ptr_;
   const off64_t data_length_;
 };
 
@@ -129,7 +133,7 @@
 
   size_t GetMapLength() const { return length_; }
 
-  void Initialize(void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
+  void Initialize(const void* map_base_ptr, off64_t cd_start_offset, size_t cd_size);
 
  private:
   const uint8_t* base_ptr_;
@@ -137,22 +141,22 @@
 };
 
 /**
- * More space efficient string representation of strings in an mmaped zipped file than
- * std::string_view or ZipString. Using ZipString as an entry in the ZipArchive hashtable wastes
- * space. ZipString stores a pointer to a string (on 64 bit, 8 bytes) and the length to read from
- * that pointer, 2 bytes. Because of alignment, the structure consumes 16 bytes, wasting 6 bytes.
- * ZipStringOffset stores a 4 byte offset from a fixed location in the memory mapped file instead
- * of the entire address, consuming 8 bytes with alignment.
+ * More space efficient string representation of strings in an mmaped zipped
+ * file than std::string_view. Using std::string_view as an entry in the
+ * ZipArchive hash table wastes space. std::string_view stores a pointer to a
+ * string (on 64 bit, 8 bytes) and the length to read from that pointer,
+ * 2 bytes. Because of alignment, the structure consumes 16 bytes, wasting
+ * 6 bytes.
+ *
+ * ZipStringOffset stores a 4 byte offset from a fixed location in the memory
+ * mapped file instead of the entire address, consuming 8 bytes with alignment.
  */
 struct ZipStringOffset {
   uint32_t name_offset;
   uint16_t name_length;
 
-  const ZipString GetZipString(const uint8_t* start) const {
-    ZipString zip_string;
-    zip_string.name = start + name_offset;
-    zip_string.name_length = name_length;
-    return zip_string;
+  const std::string_view ToStringView(const uint8_t* start) const {
+    return std::string_view{reinterpret_cast<const char*>(start + name_offset), name_length};
   }
 };
 
@@ -177,7 +181,7 @@
   ZipStringOffset* hash_table;
 
   ZipArchive(const int fd, bool assume_ownership);
-  ZipArchive(void* address, size_t length);
+  ZipArchive(const void* address, size_t length);
   ~ZipArchive();
 
   bool InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size);
diff --git a/libziparchive/zip_archive_stream_entry.cc b/libziparchive/zip_archive_stream_entry.cc
index 9ec89b1..1ec95b6 100644
--- a/libziparchive/zip_archive_stream_entry.cc
+++ b/libziparchive/zip_archive_stream_entry.cc
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/logging.h>
 #include <log/log.h>
 
 #include <ziparchive/zip_archive.h>
@@ -77,6 +78,12 @@
 }
 
 const std::vector<uint8_t>* ZipArchiveStreamEntryUncompressed::Read() {
+  // Simple sanity check. The vector should *only* be handled by this code. A caller
+  // should not const-cast and modify the capacity. This may invalidate next_out.
+  //
+  // Note: it would be better to store the results of data() across Read calls.
+  CHECK_EQ(data_.capacity(), kBufSize);
+
   if (length_ == 0) {
     return nullptr;
   }
@@ -97,7 +104,8 @@
   if (bytes < data_.size()) {
     data_.resize(bytes);
   }
-  computed_crc32_ = crc32(computed_crc32_, data_.data(), data_.size());
+  computed_crc32_ = static_cast<uint32_t>(
+      crc32(computed_crc32_, data_.data(), static_cast<uint32_t>(data_.size())));
   length_ -= bytes;
   offset_ += bytes;
   return &data_;
@@ -192,9 +200,15 @@
 }
 
 const std::vector<uint8_t>* ZipArchiveStreamEntryCompressed::Read() {
+  // Simple sanity check. The vector should *only* be handled by this code. A caller
+  // should not const-cast and modify the capacity. This may invalidate next_out.
+  //
+  // Note: it would be better to store the results of data() across Read calls.
+  CHECK_EQ(out_.capacity(), kBufSize);
+
   if (z_stream_.avail_out == 0) {
     z_stream_.next_out = out_.data();
-    z_stream_.avail_out = out_.size();
+    z_stream_.avail_out = static_cast<uint32_t>(out_.size());
     ;
   }
 
@@ -203,7 +217,9 @@
       if (compressed_length_ == 0) {
         return nullptr;
       }
-      size_t bytes = (compressed_length_ > in_.size()) ? in_.size() : compressed_length_;
+      DCHECK_LE(in_.size(), std::numeric_limits<uint32_t>::max());  // Should be buf size = 64k.
+      uint32_t bytes = (compressed_length_ > in_.size()) ? static_cast<uint32_t>(in_.size())
+                                                         : compressed_length_;
       ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle_);
       errno = 0;
       if (!archive->mapped_zip.ReadAtOffset(in_.data(), bytes, offset_)) {
@@ -230,14 +246,16 @@
 
     if (z_stream_.avail_out == 0) {
       uncompressed_length_ -= out_.size();
-      computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size());
+      computed_crc32_ = static_cast<uint32_t>(
+          crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
       return &out_;
     }
     if (zerr == Z_STREAM_END) {
       if (z_stream_.avail_out != 0) {
         // Resize the vector down to the actual size of the data.
         out_.resize(out_.size() - z_stream_.avail_out);
-        computed_crc32_ = crc32(computed_crc32_, out_.data(), out_.size());
+        computed_crc32_ = static_cast<uint32_t>(
+            crc32(computed_crc32_, out_.data(), static_cast<uint32_t>(out_.size())));
         uncompressed_length_ -= out_.size();
         return &out_;
       }
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index cea42d4..0916304 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/logging.h>
 #include <android-base/mapped_file.h>
 #include <android-base/unique_fd.h>
 #include <gtest/gtest.h>
@@ -35,13 +36,9 @@
 
 static std::string test_data_dir = android::base::GetExecutableDirectory() + "/testdata";
 
-static const std::string kMissingZip = "missing.zip";
 static const std::string kValidZip = "valid.zip";
 static const std::string kLargeZip = "large.zip";
 static const std::string kBadCrcZip = "bad_crc.zip";
-static const std::string kCrashApk = "crash.apk";
-static const std::string kBadFilenameZip = "bad_filename.zip";
-static const std::string kUpdateZip = "dummy-update.zip";
 
 static const std::vector<uint8_t> kATxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a',
                                                 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
@@ -51,41 +48,41 @@
 
 static const std::vector<uint8_t> kBTxtContents{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '\n'};
 
-static const std::string kATxtName("a.txt");
-static const std::string kBTxtName("b.txt");
-static const std::string kNonexistentTxtName("nonexistent.txt");
-static const std::string kEmptyTxtName("empty.txt");
-static const std::string kLargeCompressTxtName("compress.txt");
-static const std::string kLargeUncompressTxtName("uncompress.txt");
-
 static int32_t OpenArchiveWrapper(const std::string& name, ZipArchiveHandle* handle) {
   const std::string abs_path = test_data_dir + "/" + name;
   return OpenArchive(abs_path.c_str(), handle);
 }
 
-static void SetZipString(ZipString* zip_str, const std::string& str) {
-  zip_str->name = reinterpret_cast<const uint8_t*>(str.c_str());
-  zip_str->name_length = str.size();
-}
-
 TEST(ziparchive, Open) {
   ZipArchiveHandle handle;
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
   CloseArchive(handle);
 
-  ASSERT_EQ(-1, OpenArchiveWrapper(kBadFilenameZip, &handle));
+  ASSERT_EQ(kInvalidEntryName, OpenArchiveWrapper("bad_filename.zip", &handle));
   CloseArchive(handle);
 }
 
 TEST(ziparchive, OutOfBound) {
   ZipArchiveHandle handle;
-  ASSERT_EQ(-8, OpenArchiveWrapper(kCrashApk, &handle));
+  ASSERT_EQ(kInvalidOffset, OpenArchiveWrapper("crash.apk", &handle));
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, EmptyArchive) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(kEmptyArchive, OpenArchiveWrapper("empty.zip", &handle));
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, ZeroSizeCentralDirectory) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(kInvalidFile, OpenArchiveWrapper("zero-size-cd.zip", &handle));
   CloseArchive(handle);
 }
 
 TEST(ziparchive, OpenMissing) {
   ZipArchiveHandle handle;
-  ASSERT_NE(0, OpenArchiveWrapper(kMissingZip, &handle));
+  ASSERT_NE(0, OpenArchiveWrapper("missing.zip", &handle));
 
   // Confirm the file descriptor is not going to be mistaken for a valid one.
   ASSERT_EQ(-1, GetFileDescriptor(handle));
@@ -111,7 +108,27 @@
   close(fd);
 }
 
-static void AssertIterationOrder(const ZipString* prefix, const ZipString* suffix,
+TEST(ziparchive, Iteration_std_string_view) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  void* iteration_cookie;
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie));
+
+  ZipEntry data;
+  std::vector<std::string_view> names;
+  std::string_view name;
+  while (Next(iteration_cookie, &data, &name) == 0) names.push_back(name);
+
+  // Assert that the names are as expected.
+  std::vector<std::string_view> expected_names{"a.txt", "b.txt", "b/", "b/c.txt", "b/d.txt"};
+  std::sort(names.begin(), names.end());
+  ASSERT_EQ(expected_names, names);
+
+  CloseArchive(handle);
+}
+
+static void AssertIterationOrder(const std::string_view prefix, const std::string_view suffix,
                                  const std::vector<std::string>& expected_names_sorted) {
   ZipArchiveHandle handle;
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
@@ -122,10 +139,10 @@
   ZipEntry data;
   std::vector<std::string> names;
 
-  ZipString name;
+  std::string name;
   for (size_t i = 0; i < expected_names_sorted.size(); ++i) {
     ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
-    names.push_back(std::string(reinterpret_cast<const char*>(name.name), name.name_length));
+    names.push_back(name);
   }
 
   // End of iteration.
@@ -141,30 +158,26 @@
   static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b.txt", "b/", "b/c.txt",
                                                                   "b/d.txt"};
 
-  AssertIterationOrder(nullptr, nullptr, kExpectedMatchesSorted);
+  AssertIterationOrder("", "", kExpectedMatchesSorted);
 }
 
 TEST(ziparchive, IterationWithPrefix) {
-  ZipString prefix("b/");
   static const std::vector<std::string> kExpectedMatchesSorted = {"b/", "b/c.txt", "b/d.txt"};
 
-  AssertIterationOrder(&prefix, nullptr, kExpectedMatchesSorted);
+  AssertIterationOrder("b/", "", kExpectedMatchesSorted);
 }
 
 TEST(ziparchive, IterationWithSuffix) {
-  ZipString suffix(".txt");
   static const std::vector<std::string> kExpectedMatchesSorted = {"a.txt", "b.txt", "b/c.txt",
                                                                   "b/d.txt"};
 
-  AssertIterationOrder(nullptr, &suffix, kExpectedMatchesSorted);
+  AssertIterationOrder("", ".txt", kExpectedMatchesSorted);
 }
 
 TEST(ziparchive, IterationWithPrefixAndSuffix) {
-  ZipString prefix("b");
-  ZipString suffix(".txt");
   static const std::vector<std::string> kExpectedMatchesSorted = {"b.txt", "b/c.txt", "b/d.txt"};
 
-  AssertIterationOrder(&prefix, &suffix, kExpectedMatchesSorted);
+  AssertIterationOrder("b", ".txt", kExpectedMatchesSorted);
 }
 
 TEST(ziparchive, IterationWithBadPrefixAndSuffix) {
@@ -172,12 +185,10 @@
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
 
   void* iteration_cookie;
-  ZipString prefix("x");
-  ZipString suffix("y");
-  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, &prefix, &suffix));
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, "x", "y"));
 
   ZipEntry data;
-  ZipString name;
+  std::string name;
 
   // End of iteration.
   ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
@@ -190,9 +201,7 @@
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
 
   ZipEntry data;
-  ZipString name;
-  SetZipString(&name, kATxtName);
-  ASSERT_EQ(0, FindEntry(handle, name, &data));
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
 
   // Known facts about a.txt, from zipinfo -v.
   ASSERT_EQ(63, data.offset);
@@ -203,9 +212,28 @@
   ASSERT_EQ(static_cast<uint32_t>(0x438a8005), data.mod_time);
 
   // An entry that doesn't exist. Should be a negative return code.
-  ZipString absent_name;
-  SetZipString(&absent_name, kNonexistentTxtName);
-  ASSERT_LT(FindEntry(handle, absent_name, &data), 0);
+  ASSERT_LT(FindEntry(handle, "this file does not exist", &data), 0);
+
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, FindEntry_empty) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  ZipEntry data;
+  ASSERT_EQ(kInvalidEntryName, FindEntry(handle, "", &data));
+
+  CloseArchive(handle);
+}
+
+TEST(ziparchive, FindEntry_too_long) {
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+
+  std::string very_long_name(65536, 'x');
+  ZipEntry data;
+  ASSERT_EQ(kInvalidEntryName, FindEntry(handle, very_long_name, &data));
 
   CloseArchive(handle);
 }
@@ -215,9 +243,9 @@
   ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle));
 
   void* iteration_cookie;
-  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, nullptr, nullptr));
+  ASSERT_EQ(0, StartIteration(handle, &iteration_cookie));
 
-  ZipString name;
+  std::string name;
   ZipEntry data;
 
   ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);
@@ -232,9 +260,7 @@
 
   // An entry that's deflated.
   ZipEntry data;
-  ZipString a_name;
-  SetZipString(&a_name, kATxtName);
-  ASSERT_EQ(0, FindEntry(handle, a_name, &data));
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &data));
   const uint32_t a_size = data.uncompressed_length;
   ASSERT_EQ(a_size, kATxtContents.size());
   uint8_t* buffer = new uint8_t[a_size];
@@ -243,9 +269,7 @@
   delete[] buffer;
 
   // An entry that's stored.
-  ZipString b_name;
-  SetZipString(&b_name, kBTxtName);
-  ASSERT_EQ(0, FindEntry(handle, b_name, &data));
+  ASSERT_EQ(0, FindEntry(handle, "b.txt", &data));
   const uint32_t b_size = data.uncompressed_length;
   ASSERT_EQ(b_size, kBTxtContents.size());
   buffer = new uint8_t[b_size];
@@ -300,9 +324,7 @@
   ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EmptyEntriesTest", &handle, false));
 
   ZipEntry entry;
-  ZipString empty_name;
-  SetZipString(&empty_name, kEmptyTxtName);
-  ASSERT_EQ(0, FindEntry(handle, empty_name, &entry));
+  ASSERT_EQ(0, FindEntry(handle, "empty.txt", &entry));
   ASSERT_EQ(static_cast<uint32_t>(0), entry.uncompressed_length);
   uint8_t buffer[1];
   ASSERT_EQ(0, ExtractToMemory(handle, &entry, buffer, 1));
@@ -325,14 +347,12 @@
   ASSERT_EQ(0, OpenArchiveFd(tmp_file.fd, "EntryLargerThan32KTest", &handle, false));
 
   ZipEntry entry;
-  ZipString ab_name;
-  SetZipString(&ab_name, kAbTxtName);
-  ASSERT_EQ(0, FindEntry(handle, ab_name, &entry));
+  ASSERT_EQ(0, FindEntry(handle, kAbTxtName, &entry));
   ASSERT_EQ(kAbUncompressedSize, entry.uncompressed_length);
 
   // Extract the entry to memory.
   std::vector<uint8_t> buffer(kAbUncompressedSize);
-  ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], buffer.size()));
+  ASSERT_EQ(0, ExtractToMemory(handle, &entry, &buffer[0], static_cast<uint32_t>(buffer.size())));
 
   // Extract the entry to a file.
   TemporaryFile tmp_output_file;
@@ -384,9 +404,7 @@
   ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
 
   ZipEntry entry;
-  ZipString name;
-  SetZipString(&name, kATxtName);
-  ASSERT_EQ(0, FindEntry(handle, name, &entry));
+  ASSERT_EQ(0, FindEntry(handle, "a.txt", &entry));
   ASSERT_EQ(0, ExtractEntryToFile(handle, &entry, tmp_file.fd));
 
   // Assert that the first 8 bytes of the file haven't been clobbered.
@@ -408,23 +426,22 @@
 
 #if !defined(_WIN32)
 TEST(ziparchive, OpenFromMemory) {
-  const std::string zip_path = test_data_dir + "/" + kUpdateZip;
+  const std::string zip_path = test_data_dir + "/dummy-update.zip";
   android::base::unique_fd fd(open(zip_path.c_str(), O_RDONLY | O_BINARY));
   ASSERT_NE(-1, fd);
   struct stat sb;
   ASSERT_EQ(0, fstat(fd, &sb));
 
   // Memory map the file first and open the archive from the memory region.
-  auto file_map{android::base::MappedFile::FromFd(fd, 0, sb.st_size, PROT_READ)};
+  auto file_map{
+      android::base::MappedFile::FromFd(fd, 0, static_cast<size_t>(sb.st_size), PROT_READ)};
   ZipArchiveHandle handle;
   ASSERT_EQ(0,
             OpenArchiveFromMemory(file_map->data(), file_map->size(), zip_path.c_str(), &handle));
 
   // Assert one entry can be found and extracted correctly.
-  std::string BINARY_PATH("META-INF/com/google/android/update-binary");
-  ZipString binary_path(BINARY_PATH.c_str());
   ZipEntry binary_entry;
-  ASSERT_EQ(0, FindEntry(handle, binary_path, &binary_entry));
+  ASSERT_EQ(0, FindEntry(handle, "META-INF/com/google/android/update-binary", &binary_entry));
   TemporaryFile tmp_binary;
   ASSERT_NE(-1, tmp_binary.fd);
   ASSERT_EQ(0, ExtractEntryToFile(handle, &binary_entry, tmp_binary.fd));
@@ -433,9 +450,7 @@
 
 static void ZipArchiveStreamTest(ZipArchiveHandle& handle, const std::string& entry_name, bool raw,
                                  bool verified, ZipEntry* entry, std::vector<uint8_t>* read_data) {
-  ZipString name;
-  SetZipString(&name, entry_name);
-  ASSERT_EQ(0, FindEntry(handle, name, entry));
+  ASSERT_EQ(0, FindEntry(handle, entry_name, entry));
   std::unique_ptr<ZipArchiveStreamEntry> stream;
   if (raw) {
     stream.reset(ZipArchiveStreamEntry::CreateRaw(handle, *entry));
@@ -488,34 +503,35 @@
 
   std::vector<uint8_t> cmp_data(entry.uncompressed_length);
   ASSERT_EQ(entry.uncompressed_length, read_data.size());
-  ASSERT_EQ(0, ExtractToMemory(handle, &entry, cmp_data.data(), cmp_data.size()));
+  ASSERT_EQ(
+      0, ExtractToMemory(handle, &entry, cmp_data.data(), static_cast<uint32_t>(cmp_data.size())));
   ASSERT_TRUE(memcmp(read_data.data(), cmp_data.data(), read_data.size()) == 0);
 
   CloseArchive(handle);
 }
 
 TEST(ziparchive, StreamCompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kATxtName, kATxtContents, false);
+  ZipArchiveStreamTestUsingContents(kValidZip, "a.txt", kATxtContents, false);
 }
 
 TEST(ziparchive, StreamUncompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kBTxtName, kBTxtContents, false);
+  ZipArchiveStreamTestUsingContents(kValidZip, "b.txt", kBTxtContents, false);
 }
 
 TEST(ziparchive, StreamRawCompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kATxtName, kATxtContentsCompressed, true);
+  ZipArchiveStreamTestUsingContents(kValidZip, "a.txt", kATxtContentsCompressed, true);
 }
 
 TEST(ziparchive, StreamRawUncompressed) {
-  ZipArchiveStreamTestUsingContents(kValidZip, kBTxtName, kBTxtContents, true);
+  ZipArchiveStreamTestUsingContents(kValidZip, "b.txt", kBTxtContents, true);
 }
 
 TEST(ziparchive, StreamLargeCompressed) {
-  ZipArchiveStreamTestUsingMemory(kLargeZip, kLargeCompressTxtName);
+  ZipArchiveStreamTestUsingMemory(kLargeZip, "compress.txt");
 }
 
 TEST(ziparchive, StreamLargeUncompressed) {
-  ZipArchiveStreamTestUsingMemory(kLargeZip, kLargeUncompressTxtName);
+  ZipArchiveStreamTestUsingMemory(kLargeZip, "uncompress.txt");
 }
 
 TEST(ziparchive, StreamCompressedBadCrc) {
@@ -524,7 +540,7 @@
 
   ZipEntry entry;
   std::vector<uint8_t> read_data;
-  ZipArchiveStreamTest(handle, kATxtName, false, false, &entry, &read_data);
+  ZipArchiveStreamTest(handle, "a.txt", false, false, &entry, &read_data);
 
   CloseArchive(handle);
 }
@@ -535,7 +551,7 @@
 
   ZipEntry entry;
   std::vector<uint8_t> read_data;
-  ZipArchiveStreamTest(handle, kBTxtName, false, false, &entry, &read_data);
+  ZipArchiveStreamTest(handle, "b.txt", false, false, &entry, &read_data);
 
   CloseArchive(handle);
 }
@@ -585,11 +601,7 @@
   // an entry whose name is "name" and whose size is 12 (contents =
   // "abdcdefghijk").
   ZipEntry entry;
-  ZipString name;
-  std::string name_str = "name";
-  SetZipString(&name, name_str);
-
-  ASSERT_EQ(0, FindEntry(handle, name, &entry));
+  ASSERT_EQ(0, FindEntry(handle, "name", &entry));
   ASSERT_EQ(static_cast<uint32_t>(12), entry.uncompressed_length);
 
   entry_out->resize(12);
@@ -636,7 +648,8 @@
 
   // Out of bounds.
   ASSERT_STREQ("Unknown return code", ErrorCodeString(1));
-  ASSERT_STREQ("Unknown return code", ErrorCodeString(-13));
+  ASSERT_STRNE("Unknown return code", ErrorCodeString(kLastErrorCode));
+  ASSERT_STREQ("Unknown return code", ErrorCodeString(kLastErrorCode - 1));
 
   ASSERT_STREQ("I/O error", ErrorCodeString(kIoError));
 }
@@ -687,7 +700,7 @@
   ASSERT_TRUE(android::base::WriteFully(tmp_file.fd, &kZipFileWithBrokenLfhSignature[0],
                                         kZipFileWithBrokenLfhSignature.size()));
   ZipArchiveHandle handle;
-  ASSERT_EQ(-1, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle, false));
+  ASSERT_EQ(kInvalidFile, OpenArchiveFd(tmp_file.fd, "LeadingNonZipBytes", &handle, false));
 }
 
 class VectorReader : public zip_archive::Reader {
@@ -737,8 +750,8 @@
 };
 
 TEST(ziparchive, Inflate) {
-  const uint32_t compressed_length = kATxtContentsCompressed.size();
-  const uint32_t uncompressed_length = kATxtContents.size();
+  const uint32_t compressed_length = static_cast<uint32_t>(kATxtContentsCompressed.size());
+  const uint32_t uncompressed_length = static_cast<uint32_t>(kATxtContents.size());
 
   const VectorReader reader(kATxtContentsCompressed);
   {
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index 0df0fa5..67279a6 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -130,7 +130,7 @@
   return error_code;
 }
 
-int32_t ZipWriter::StartEntry(const char* path, size_t flags) {
+int32_t ZipWriter::StartEntry(std::string_view path, size_t flags) {
   uint32_t alignment = 0;
   if (flags & kAlign32) {
     flags &= ~kAlign32;
@@ -139,11 +139,11 @@
   return StartAlignedEntryWithTime(path, flags, time_t(), alignment);
 }
 
-int32_t ZipWriter::StartAlignedEntry(const char* path, size_t flags, uint32_t alignment) {
+int32_t ZipWriter::StartAlignedEntry(std::string_view path, size_t flags, uint32_t alignment) {
   return StartAlignedEntryWithTime(path, flags, time_t(), alignment);
 }
 
-int32_t ZipWriter::StartEntryWithTime(const char* path, size_t flags, time_t time) {
+int32_t ZipWriter::StartEntryWithTime(std::string_view path, size_t flags, time_t time) {
   uint32_t alignment = 0;
   if (flags & kAlign32) {
     flags &= ~kAlign32;
@@ -169,8 +169,8 @@
     year = 80;
   }
 
-  *out_date = (year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday;
-  *out_time = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1;
+  *out_date = static_cast<uint16_t>((year - 80) << 9 | (ptm->tm_mon + 1) << 5 | ptm->tm_mday);
+  *out_time = static_cast<uint16_t>(ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1);
 }
 
 static void CopyFromFileEntry(const ZipWriter::FileEntry& src, bool use_data_descriptor,
@@ -193,16 +193,22 @@
   dst->compression_method = src.compression_method;
   dst->last_mod_time = src.last_mod_time;
   dst->last_mod_date = src.last_mod_date;
-  dst->file_name_length = src.path.size();
+  DCHECK_LE(src.path.size(), std::numeric_limits<uint16_t>::max());
+  dst->file_name_length = static_cast<uint16_t>(src.path.size());
   dst->extra_field_length = src.padding_length;
 }
 
-int32_t ZipWriter::StartAlignedEntryWithTime(const char* path, size_t flags, time_t time,
+int32_t ZipWriter::StartAlignedEntryWithTime(std::string_view path, size_t flags, time_t time,
                                              uint32_t alignment) {
   if (state_ != State::kWritingZip) {
     return kInvalidState;
   }
 
+  // Can only have 16535 entries because of zip records.
+  if (files_.size() == std::numeric_limits<uint16_t>::max()) {
+    return HandleError(kIoError);
+  }
+
   if (flags & kAlign32) {
     return kInvalidAlign32Flag;
   }
@@ -210,10 +216,17 @@
   if (powerof2(alignment) == 0) {
     return kInvalidAlignment;
   }
+  if (alignment > std::numeric_limits<uint16_t>::max()) {
+    return kInvalidAlignment;
+  }
 
   FileEntry file_entry = {};
   file_entry.local_file_header_offset = current_offset_;
   file_entry.path = path;
+  // No support for larger than 4GB files.
+  if (file_entry.local_file_header_offset > std::numeric_limits<uint32_t>::max()) {
+    return HandleError(kIoError);
+  }
 
   if (!IsValidEntryName(reinterpret_cast<const uint8_t*>(file_entry.path.data()),
                         file_entry.path.size())) {
@@ -234,13 +247,24 @@
   ExtractTimeAndDate(time, &file_entry.last_mod_time, &file_entry.last_mod_date);
 
   off_t offset = current_offset_ + sizeof(LocalFileHeader) + file_entry.path.size();
-  std::vector<char> zero_padding;
+  // prepare a pre-zeroed memory page in case when we need to pad some aligned data.
+  static constexpr auto kPageSize = 4096;
+  static constexpr char kSmallZeroPadding[kPageSize] = {};
+  // use this buffer if our preallocated one is too small
+  std::vector<char> zero_padding_big;
+  const char* zero_padding = nullptr;
+
   if (alignment != 0 && (offset & (alignment - 1))) {
     // Pad the extra field so the data will be aligned.
-    uint16_t padding = alignment - (offset % alignment);
+    uint16_t padding = static_cast<uint16_t>(alignment - (offset % alignment));
     file_entry.padding_length = padding;
     offset += padding;
-    zero_padding.resize(padding, 0);
+    if (padding <= std::size(kSmallZeroPadding)) {
+        zero_padding = kSmallZeroPadding;
+    } else {
+        zero_padding_big.resize(padding, 0);
+        zero_padding = zero_padding_big.data();
+    }
   }
 
   LocalFileHeader header = {};
@@ -252,11 +276,11 @@
     return HandleError(kIoError);
   }
 
-  if (fwrite(path, sizeof(*path), file_entry.path.size(), file_) != file_entry.path.size()) {
+  if (fwrite(path.data(), 1, path.size(), file_) != path.size()) {
     return HandleError(kIoError);
   }
 
-  if (file_entry.padding_length != 0 && fwrite(zero_padding.data(), 1, file_entry.padding_length,
+  if (file_entry.padding_length != 0 && fwrite(zero_padding, 1, file_entry.padding_length,
                                                file_) != file_entry.padding_length) {
     return HandleError(kIoError);
   }
@@ -314,7 +338,8 @@
   }
 
   z_stream_->next_out = buffer_.data();
-  z_stream_->avail_out = buffer_.size();
+  DCHECK_EQ(buffer_.size(), kBufSize);
+  z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
   return kNoError;
 }
 
@@ -322,25 +347,31 @@
   if (state_ != State::kWritingEntry) {
     return HandleError(kInvalidState);
   }
+  // Need to be able to mark down data correctly.
+  if (len + static_cast<uint64_t>(current_file_entry_.uncompressed_size) >
+      std::numeric_limits<uint32_t>::max()) {
+    return HandleError(kIoError);
+  }
+  uint32_t len32 = static_cast<uint32_t>(len);
 
   int32_t result = kNoError;
   if (current_file_entry_.compression_method & kCompressDeflated) {
-    result = CompressBytes(&current_file_entry_, data, len);
+    result = CompressBytes(&current_file_entry_, data, len32);
   } else {
-    result = StoreBytes(&current_file_entry_, data, len);
+    result = StoreBytes(&current_file_entry_, data, len32);
   }
 
   if (result != kNoError) {
     return result;
   }
 
-  current_file_entry_.crc32 =
-      crc32(current_file_entry_.crc32, reinterpret_cast<const Bytef*>(data), len);
-  current_file_entry_.uncompressed_size += len;
+  current_file_entry_.crc32 = static_cast<uint32_t>(
+      crc32(current_file_entry_.crc32, reinterpret_cast<const Bytef*>(data), len32));
+  current_file_entry_.uncompressed_size += len32;
   return kNoError;
 }
 
-int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, size_t len) {
+int32_t ZipWriter::StoreBytes(FileEntry* file, const void* data, uint32_t len) {
   CHECK(state_ == State::kWritingEntry);
 
   if (fwrite(data, 1, len, file_) != len) {
@@ -351,7 +382,7 @@
   return kNoError;
 }
 
-int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, size_t len) {
+int32_t ZipWriter::CompressBytes(FileEntry* file, const void* data, uint32_t len) {
   CHECK(state_ == State::kWritingEntry);
   CHECK(z_stream_);
   CHECK(z_stream_->next_out != nullptr);
@@ -379,7 +410,8 @@
 
       // Reset the output buffer for the next input.
       z_stream_->next_out = buffer_.data();
-      z_stream_->avail_out = buffer_.size();
+      DCHECK_EQ(buffer_.size(), kBufSize);
+      z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
     }
   }
   return kNoError;
@@ -404,7 +436,8 @@
     current_offset_ += write_bytes;
 
     z_stream_->next_out = buffer_.data();
-    z_stream_->avail_out = buffer_.size();
+    DCHECK_EQ(buffer_.size(), kBufSize);
+    z_stream_->avail_out = static_cast<uint32_t>(buffer_.size());
   }
   if (zerr != Z_STREAM_END) {
     return HandleError(kZlibError);
@@ -422,6 +455,11 @@
   return kNoError;
 }
 
+bool ZipWriter::ShouldUseDataDescriptor() const {
+  // Only use a trailing "data descriptor" if the output isn't seekable.
+  return !seekable_;
+}
+
 int32_t ZipWriter::FinishEntry() {
   if (state_ != State::kWritingEntry) {
     return kInvalidState;
@@ -434,7 +472,7 @@
     }
   }
 
-  if ((current_file_entry_.compression_method & kCompressDeflated) || !seekable_) {
+  if (ShouldUseDataDescriptor()) {
     // Some versions of ZIP don't allow STORED data to have a trailing DataDescriptor.
     // If this file is not seekable, or if the data is compressed, write a DataDescriptor.
     const uint32_t sig = DataDescriptor::kOptSignature;
@@ -482,7 +520,7 @@
   for (FileEntry& file : files_) {
     CentralDirectoryRecord cdr = {};
     cdr.record_signature = CentralDirectoryRecord::kSignature;
-    if ((file.compression_method & kCompressDeflated) || !seekable_) {
+    if (ShouldUseDataDescriptor()) {
       cdr.gpb_flags |= kGPBDDFlagMask;
     }
     cdr.compression_method = file.compression_method;
@@ -491,7 +529,11 @@
     cdr.crc32 = file.crc32;
     cdr.compressed_size = file.compressed_size;
     cdr.uncompressed_size = file.uncompressed_size;
-    cdr.file_name_length = file.path.size();
+    // Checked in IsValidEntryName.
+    DCHECK_LE(file.path.size(), std::numeric_limits<uint16_t>::max());
+    cdr.file_name_length = static_cast<uint16_t>(file.path.size());
+    // Checked in StartAlignedEntryWithTime.
+    DCHECK_LE(file.local_file_header_offset, std::numeric_limits<uint32_t>::max());
     cdr.local_file_header_offset = static_cast<uint32_t>(file.local_file_header_offset);
     if (fwrite(&cdr, sizeof(cdr), 1, file_) != 1) {
       return HandleError(kIoError);
@@ -508,10 +550,15 @@
   er.eocd_signature = EocdRecord::kSignature;
   er.disk_num = 0;
   er.cd_start_disk = 0;
-  er.num_records_on_disk = files_.size();
-  er.num_records = files_.size();
-  er.cd_size = current_offset_ - startOfCdr;
-  er.cd_start_offset = startOfCdr;
+  // Checked when adding entries.
+  DCHECK_LE(files_.size(), std::numeric_limits<uint16_t>::max());
+  er.num_records_on_disk = static_cast<uint16_t>(files_.size());
+  er.num_records = static_cast<uint16_t>(files_.size());
+  if (current_offset_ > std::numeric_limits<uint32_t>::max()) {
+    return HandleError(kIoError);
+  }
+  er.cd_size = static_cast<uint32_t>(current_offset_ - startOfCdr);
+  er.cd_start_offset = static_cast<uint32_t>(startOfCdr);
 
   if (fwrite(&er, sizeof(er), 1, file_) != 1) {
     return HandleError(kIoError);
diff --git a/libziparchive/zip_writer_test.cc b/libziparchive/zip_writer_test.cc
index c284273..d324d4b 100644
--- a/libziparchive/zip_writer_test.cc
+++ b/libziparchive/zip_writer_test.cc
@@ -62,7 +62,7 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
   EXPECT_EQ(kCompressStored, data.method);
   EXPECT_EQ(0u, data.has_data_descriptor);
   EXPECT_EQ(strlen(expected), data.compressed_length);
@@ -95,19 +95,19 @@
 
   ZipEntry data;
 
-  ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
   EXPECT_EQ(kCompressStored, data.method);
   EXPECT_EQ(2u, data.compressed_length);
   ASSERT_EQ(2u, data.uncompressed_length);
   ASSERT_TRUE(AssertFileEntryContentsEq("he", handle, &data));
 
-  ASSERT_EQ(0, FindEntry(handle, ZipString("file/file.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "file/file.txt", &data));
   EXPECT_EQ(kCompressStored, data.method);
   EXPECT_EQ(3u, data.compressed_length);
   ASSERT_EQ(3u, data.uncompressed_length);
   ASSERT_TRUE(AssertFileEntryContentsEq("llo", handle, &data));
 
-  ASSERT_EQ(0, FindEntry(handle, ZipString("file/file2.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "file/file2.txt", &data));
   EXPECT_EQ(kCompressStored, data.method);
   EXPECT_EQ(0u, data.compressed_length);
   EXPECT_EQ(0u, data.uncompressed_length);
@@ -129,7 +129,7 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "align.txt", &data));
   EXPECT_EQ(0, data.offset & 0x03);
 
   CloseArchive(handle);
@@ -163,7 +163,7 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "align.txt", &data));
   EXPECT_EQ(0, data.offset & 0x03);
 
   struct tm mod = data.GetModificationTime();
@@ -191,7 +191,7 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "align.txt", &data));
   EXPECT_EQ(0, data.offset & 0xfff);
 
   CloseArchive(handle);
@@ -213,7 +213,7 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("align.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "align.txt", &data));
   EXPECT_EQ(0, data.offset & 0xfff);
 
   struct tm mod = data.GetModificationTime();
@@ -241,8 +241,9 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
   EXPECT_EQ(kCompressDeflated, data.method);
+  EXPECT_EQ(0u, data.has_data_descriptor);
   ASSERT_EQ(4u, data.uncompressed_length);
   ASSERT_TRUE(AssertFileEntryContentsEq("helo", handle, &data));
 
@@ -257,7 +258,7 @@
   std::vector<uint8_t> buffer(kBufSize);
   size_t prev = 1;
   for (size_t i = 0; i < kBufSize; i++) {
-    buffer[i] = i + prev;
+    buffer[i] = static_cast<uint8_t>(i + prev);
     prev = i;
   }
 
@@ -273,13 +274,14 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("file.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
   EXPECT_EQ(kCompressDeflated, data.method);
   EXPECT_EQ(kBufSize, data.uncompressed_length);
 
   std::vector<uint8_t> decompress(kBufSize);
   memset(decompress.data(), 0, kBufSize);
-  ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(), decompress.size()));
+  ASSERT_EQ(0, ExtractToMemory(handle, &data, decompress.data(),
+                               static_cast<uint32_t>(decompress.size())));
   EXPECT_EQ(0, memcmp(decompress.data(), buffer.data(), kBufSize))
       << "Input buffer and output buffer are different.";
 
@@ -339,17 +341,40 @@
   ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
 
   ZipEntry data;
-  ASSERT_EQ(0, FindEntry(handle, ZipString("keep.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "keep.txt", &data));
   ASSERT_TRUE(AssertFileEntryContentsEq(kKeepThis, handle, &data));
 
-  ASSERT_NE(0, FindEntry(handle, ZipString("drop.txt"), &data));
+  ASSERT_NE(0, FindEntry(handle, "drop.txt", &data));
 
-  ASSERT_EQ(0, FindEntry(handle, ZipString("replace.txt"), &data));
+  ASSERT_EQ(0, FindEntry(handle, "replace.txt", &data));
   ASSERT_TRUE(AssertFileEntryContentsEq(kReplaceWithThis, handle, &data));
 
   CloseArchive(handle);
 }
 
+TEST_F(zipwriter, WriteToUnseekableFile) {
+  const char* expected = "hello";
+  ZipWriter writer(file_);
+  writer.seekable_ = false;
+
+  ASSERT_EQ(0, writer.StartEntry("file.txt", 0));
+  ASSERT_EQ(0, writer.WriteBytes(expected, strlen(expected)));
+  ASSERT_EQ(0, writer.FinishEntry());
+  ASSERT_EQ(0, writer.Finish());
+  ASSERT_GE(0, lseek(fd_, 0, SEEK_SET));
+
+  ZipArchiveHandle handle;
+  ASSERT_EQ(0, OpenArchiveFd(fd_, "temp", &handle, false));
+  ZipEntry data;
+  ASSERT_EQ(0, FindEntry(handle, "file.txt", &data));
+  EXPECT_EQ(kCompressStored, data.method);
+  EXPECT_EQ(1u, data.has_data_descriptor);
+  EXPECT_EQ(strlen(expected), data.compressed_length);
+  ASSERT_EQ(strlen(expected), data.uncompressed_length);
+  ASSERT_TRUE(AssertFileEntryContentsEq(expected, handle, &data));
+  CloseArchive(handle);
+}
+
 TEST_F(zipwriter, TruncateFileAfterBackup) {
   ZipWriter writer(file_);
 
@@ -391,7 +416,7 @@
   actual.resize(expected.size());
 
   uint8_t* buffer = reinterpret_cast<uint8_t*>(&*actual.begin());
-  if (ExtractToMemory(handle, zip_entry, buffer, actual.size()) != 0) {
+  if (ExtractToMemory(handle, zip_entry, buffer, static_cast<uint32_t>(actual.size())) != 0) {
     return ::testing::AssertionFailure() << "failed to extract entry";
   }
 
diff --git a/libziparchive/ziptool-tests.xml b/libziparchive/ziptool-tests.xml
new file mode 100644
index 0000000..211119f
--- /dev/null
+++ b/libziparchive/ziptool-tests.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for running ziptool-tests through Atest or in Infra">
+    <option name="test-suite-tag" value="ziptool-tests" />
+    <!-- This test requires a device, so it's not annotated with a null-device. -->
+    <test class="com.android.tradefed.testtype.binary.ExecutableHostTest" >
+        <option name="binary" value="run-ziptool-tests-on-android.sh" />
+        <!-- Test script assumes a relative path with the cli-tests/ folders. -->
+        <option name="relative-path-execution" value="true" />
+        <!-- Tests shouldn't be that long but set 15m to be safe. -->
+        <option name="per-binary-timeout" value="15m" />
+    </test>
+</configuration>
diff --git a/libziparchive/ziptool.cpp b/libziparchive/ziptool.cpp
new file mode 100644
index 0000000..dd42e90
--- /dev/null
+++ b/libziparchive/ziptool.cpp
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2017 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 <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <set>
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <ziparchive/zip_archive.h>
+
+using android::base::EndsWith;
+using android::base::StartsWith;
+
+enum OverwriteMode {
+  kAlways,
+  kNever,
+  kPrompt,
+};
+
+enum Role {
+  kUnzip,
+  kZipinfo,
+};
+
+static Role role;
+static OverwriteMode overwrite_mode = kPrompt;
+static bool flag_1 = false;
+static std::string flag_d;
+static bool flag_l = false;
+static bool flag_p = false;
+static bool flag_q = false;
+static bool flag_v = false;
+static bool flag_x = false;
+static const char* archive_name = nullptr;
+static std::set<std::string> includes;
+static std::set<std::string> excludes;
+static uint64_t total_uncompressed_length = 0;
+static uint64_t total_compressed_length = 0;
+static size_t file_count = 0;
+
+static const char* g_progname;
+
+static void die(int error, const char* fmt, ...) {
+  va_list ap;
+
+  va_start(ap, fmt);
+  fprintf(stderr, "%s: ", g_progname);
+  vfprintf(stderr, fmt, ap);
+  if (error != 0) fprintf(stderr, ": %s", strerror(error));
+  fprintf(stderr, "\n");
+  va_end(ap);
+  exit(1);
+}
+
+static bool ShouldInclude(const std::string& name) {
+  // Explicitly excluded?
+  if (!excludes.empty()) {
+    for (const auto& exclude : excludes) {
+      if (!fnmatch(exclude.c_str(), name.c_str(), 0)) return false;
+    }
+  }
+
+  // Implicitly included?
+  if (includes.empty()) return true;
+
+  // Explicitly included?
+  for (const auto& include : includes) {
+    if (!fnmatch(include.c_str(), name.c_str(), 0)) return true;
+  }
+  return false;
+}
+
+static bool MakeDirectoryHierarchy(const std::string& path) {
+  // stat rather than lstat because a symbolic link to a directory is fine too.
+  struct stat sb;
+  if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) return true;
+
+  // Ensure the parent directories exist first.
+  if (!MakeDirectoryHierarchy(android::base::Dirname(path))) return false;
+
+  // Then try to create this directory.
+  return (mkdir(path.c_str(), 0777) != -1);
+}
+
+static float CompressionRatio(int64_t uncompressed, int64_t compressed) {
+  if (uncompressed == 0) return 0;
+  return static_cast<float>(100LL * (uncompressed - compressed)) /
+         static_cast<float>(uncompressed);
+}
+
+static void MaybeShowHeader(ZipArchiveHandle zah) {
+  if (role == kUnzip) {
+    // unzip has three formats.
+    if (!flag_q) printf("Archive:  %s\n", archive_name);
+    if (flag_v) {
+      printf(
+          " Length   Method    Size  Cmpr    Date    Time   CRC-32   Name\n"
+          "--------  ------  ------- ---- ---------- ----- --------  ----\n");
+    } else if (flag_l) {
+      printf(
+          "  Length      Date    Time    Name\n"
+          "---------  ---------- -----   ----\n");
+    }
+  } else {
+    // zipinfo.
+    if (!flag_1 && includes.empty() && excludes.empty()) {
+      ZipArchiveInfo info{GetArchiveInfo(zah)};
+      printf("Archive:  %s\n", archive_name);
+      printf("Zip file size: %" PRId64 " bytes, number of entries: %zu\n", info.archive_size,
+             info.entry_count);
+    }
+  }
+}
+
+static void MaybeShowFooter() {
+  if (role == kUnzip) {
+    if (flag_v) {
+      printf(
+          "--------          -------  ---                            -------\n"
+          "%8" PRId64 "         %8" PRId64 " %3.0f%%                            %zu file%s\n",
+          total_uncompressed_length, total_compressed_length,
+          CompressionRatio(total_uncompressed_length, total_compressed_length), file_count,
+          (file_count == 1) ? "" : "s");
+    } else if (flag_l) {
+      printf(
+          "---------                     -------\n"
+          "%9" PRId64 "                     %zu file%s\n",
+          total_uncompressed_length, file_count, (file_count == 1) ? "" : "s");
+    }
+  } else {
+    if (!flag_1 && includes.empty() && excludes.empty()) {
+      printf("%zu files, %" PRId64 " bytes uncompressed, %" PRId64 " bytes compressed:  %.1f%%\n",
+             file_count, total_uncompressed_length, total_compressed_length,
+             CompressionRatio(total_uncompressed_length, total_compressed_length));
+    }
+  }
+}
+
+static bool PromptOverwrite(const std::string& dst) {
+  // TODO: [r]ename not implemented because it doesn't seem useful.
+  printf("replace %s? [y]es, [n]o, [A]ll, [N]one: ", dst.c_str());
+  fflush(stdout);
+  while (true) {
+    char* line = nullptr;
+    size_t n;
+    if (getline(&line, &n, stdin) == -1) {
+      die(0, "(EOF/read error; assuming [N]one...)");
+      overwrite_mode = kNever;
+      return false;
+    }
+    if (n == 0) continue;
+    char cmd = line[0];
+    free(line);
+    switch (cmd) {
+      case 'y':
+        return true;
+      case 'n':
+        return false;
+      case 'A':
+        overwrite_mode = kAlways;
+        return true;
+      case 'N':
+        overwrite_mode = kNever;
+        return false;
+    }
+  }
+}
+
+static void ExtractToPipe(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
+  // We need to extract to memory because ExtractEntryToFile insists on
+  // being able to seek and truncate, and you can't do that with stdout.
+  uint8_t* buffer = new uint8_t[entry.uncompressed_length];
+  int err = ExtractToMemory(zah, &entry, buffer, entry.uncompressed_length);
+  if (err < 0) {
+    die(0, "failed to extract %s: %s", name.c_str(), ErrorCodeString(err));
+  }
+  if (!android::base::WriteFully(1, buffer, entry.uncompressed_length)) {
+    die(errno, "failed to write %s to stdout", name.c_str());
+  }
+  delete[] buffer;
+}
+
+static void ExtractOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
+  // Bad filename?
+  if (StartsWith(name, "/") || StartsWith(name, "../") || name.find("/../") != std::string::npos) {
+    die(0, "bad filename %s", name.c_str());
+  }
+
+  // Where are we actually extracting to (for human-readable output)?
+  // flag_d is the empty string if -d wasn't used, or has a trailing '/'
+  // otherwise.
+  std::string dst = flag_d + name;
+
+  // Ensure the directory hierarchy exists.
+  if (!MakeDirectoryHierarchy(android::base::Dirname(name))) {
+    die(errno, "couldn't create directory hierarchy for %s", dst.c_str());
+  }
+
+  // An entry in a zip file can just be a directory itself.
+  if (EndsWith(name, "/")) {
+    if (mkdir(name.c_str(), entry.unix_mode) == -1) {
+      // If the directory already exists, that's fine.
+      if (errno == EEXIST) {
+        struct stat sb;
+        if (stat(name.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) return;
+      }
+      die(errno, "couldn't extract directory %s", dst.c_str());
+    }
+    return;
+  }
+
+  // Create the file.
+  int fd = open(name.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC | O_EXCL, entry.unix_mode);
+  if (fd == -1 && errno == EEXIST) {
+    if (overwrite_mode == kNever) return;
+    if (overwrite_mode == kPrompt && !PromptOverwrite(dst)) return;
+    // Either overwrite_mode is kAlways or the user consented to this specific case.
+    fd = open(name.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, entry.unix_mode);
+  }
+  if (fd == -1) die(errno, "couldn't create file %s", dst.c_str());
+
+  // Actually extract into the file.
+  if (!flag_q) printf("  inflating: %s\n", dst.c_str());
+  int err = ExtractEntryToFile(zah, &entry, fd);
+  if (err < 0) die(0, "failed to extract %s: %s", dst.c_str(), ErrorCodeString(err));
+  close(fd);
+}
+
+static void ListOne(const ZipEntry& entry, const std::string& name) {
+  tm t = entry.GetModificationTime();
+  char time[32];
+  snprintf(time, sizeof(time), "%04d-%02d-%02d %02d:%02d", t.tm_year + 1900, t.tm_mon + 1,
+           t.tm_mday, t.tm_hour, t.tm_min);
+  if (flag_v) {
+    printf("%8d  %s  %7d %3.0f%% %s %08x  %s\n", entry.uncompressed_length,
+           (entry.method == kCompressStored) ? "Stored" : "Defl:N", entry.compressed_length,
+           CompressionRatio(entry.uncompressed_length, entry.compressed_length), time, entry.crc32,
+           name.c_str());
+  } else {
+    printf("%9d  %s   %s\n", entry.uncompressed_length, time, name.c_str());
+  }
+}
+
+static void InfoOne(const ZipEntry& entry, const std::string& name) {
+  if (flag_1) {
+    // "android-ndk-r19b/sources/android/NOTICE"
+    printf("%s\n", name.c_str());
+    return;
+  }
+
+  int version = entry.version_made_by & 0xff;
+  int os = (entry.version_made_by >> 8) & 0xff;
+
+  // TODO: Support suid/sgid? Non-Unix/non-FAT host file system attributes?
+  const char* src_fs = "???";
+  char mode[] = "???       ";
+  if (os == 0) {
+    src_fs = "fat";
+    // https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
+    int attrs = entry.external_file_attributes & 0xff;
+    mode[0] = (attrs & 0x10) ? 'd' : '-';
+    mode[1] = 'r';
+    mode[2] = (attrs & 0x01) ? '-' : 'w';
+    // The man page also mentions ".btm", but that seems to be obsolete?
+    mode[3] = EndsWith(name, ".exe") || EndsWith(name, ".com") || EndsWith(name, ".bat") ||
+                      EndsWith(name, ".cmd")
+                  ? 'x'
+                  : '-';
+    mode[4] = (attrs & 0x20) ? 'a' : '-';
+    mode[5] = (attrs & 0x02) ? 'h' : '-';
+    mode[6] = (attrs & 0x04) ? 's' : '-';
+  } else if (os == 3) {
+    src_fs = "unx";
+    mode[0] = S_ISDIR(entry.unix_mode) ? 'd' : (S_ISREG(entry.unix_mode) ? '-' : '?');
+    mode[1] = entry.unix_mode & S_IRUSR ? 'r' : '-';
+    mode[2] = entry.unix_mode & S_IWUSR ? 'w' : '-';
+    mode[3] = entry.unix_mode & S_IXUSR ? 'x' : '-';
+    mode[4] = entry.unix_mode & S_IRGRP ? 'r' : '-';
+    mode[5] = entry.unix_mode & S_IWGRP ? 'w' : '-';
+    mode[6] = entry.unix_mode & S_IXGRP ? 'x' : '-';
+    mode[7] = entry.unix_mode & S_IROTH ? 'r' : '-';
+    mode[8] = entry.unix_mode & S_IWOTH ? 'w' : '-';
+    mode[9] = entry.unix_mode & S_IXOTH ? 'x' : '-';
+  }
+
+  char method[5] = "stor";
+  if (entry.method == kCompressDeflated) {
+    snprintf(method, sizeof(method), "def%c", "NXFS"[(entry.gpbf >> 1) & 0x3]);
+  }
+
+  // TODO: zipinfo (unlike unzip) sometimes uses time zone?
+  // TODO: this uses 4-digit years because we're not barbarians unless interoperability forces it.
+  tm t = entry.GetModificationTime();
+  char time[32];
+  snprintf(time, sizeof(time), "%04d-%02d-%02d %02d:%02d", t.tm_year + 1900, t.tm_mon + 1,
+           t.tm_mday, t.tm_hour, t.tm_min);
+
+  // "-rw-r--r--  3.0 unx      577 t- defX 19-Feb-12 16:09 android-ndk-r19b/sources/android/NOTICE"
+  printf("%s %2d.%d %s %8d %c%c %s %s %s\n", mode, version / 10, version % 10, src_fs,
+         entry.uncompressed_length, entry.is_text ? 't' : 'b',
+         entry.has_data_descriptor ? 'X' : 'x', method, time, name.c_str());
+}
+
+static void ProcessOne(ZipArchiveHandle zah, ZipEntry& entry, const std::string& name) {
+  if (role == kUnzip) {
+    if (flag_l || flag_v) {
+      // -l or -lv or -lq or -v.
+      ListOne(entry, name);
+    } else {
+      // Actually extract.
+      if (flag_p) {
+        ExtractToPipe(zah, entry, name);
+      } else {
+        ExtractOne(zah, entry, name);
+      }
+    }
+  } else {
+    // zipinfo or zipinfo -1.
+    InfoOne(entry, name);
+  }
+  total_uncompressed_length += entry.uncompressed_length;
+  total_compressed_length += entry.compressed_length;
+  ++file_count;
+}
+
+static void ProcessAll(ZipArchiveHandle zah) {
+  MaybeShowHeader(zah);
+
+  // libziparchive iteration order doesn't match the central directory.
+  // We could sort, but that would cost extra and wouldn't match either.
+  void* cookie;
+  int err = StartIteration(zah, &cookie);
+  if (err != 0) {
+    die(0, "couldn't iterate %s: %s", archive_name, ErrorCodeString(err));
+  }
+
+  ZipEntry entry;
+  std::string name;
+  while ((err = Next(cookie, &entry, &name)) >= 0) {
+    if (ShouldInclude(name)) ProcessOne(zah, entry, name);
+  }
+
+  if (err < -1) die(0, "failed iterating %s: %s", archive_name, ErrorCodeString(err));
+  EndIteration(cookie);
+
+  MaybeShowFooter();
+}
+
+static void ShowHelp(bool full) {
+  if (role == kUnzip) {
+    fprintf(full ? stdout : stderr, "usage: unzip [-d DIR] [-lnopqv] ZIP [FILE...] [-x FILE...]\n");
+    if (!full) exit(EXIT_FAILURE);
+
+    printf(
+        "\n"
+        "Extract FILEs from ZIP archive. Default is all files. Both the include and\n"
+        "exclude (-x) lists use shell glob patterns.\n"
+        "\n"
+        "-d DIR	Extract into DIR\n"
+        "-l	List contents (-lq excludes archive name, -lv is verbose)\n"
+        "-n	Never overwrite files (default: prompt)\n"
+        "-o	Always overwrite files\n"
+        "-p	Pipe to stdout\n"
+        "-q	Quiet\n"
+        "-v	List contents verbosely\n"
+        "-x FILE	Exclude files\n");
+  } else {
+    fprintf(full ? stdout : stderr, "usage: zipinfo [-1] ZIP [FILE...] [-x FILE...]\n");
+    if (!full) exit(EXIT_FAILURE);
+
+    printf(
+        "\n"
+        "Show information about FILEs from ZIP archive. Default is all files.\n"
+        "Both the include and exclude (-x) lists use shell glob patterns.\n"
+        "\n"
+        "-1	Show filenames only, one per line\n"
+        "-x FILE	Exclude files\n");
+  }
+  exit(EXIT_SUCCESS);
+}
+
+static void HandleCommonOption(int opt) {
+  switch (opt) {
+    case 'h':
+      ShowHelp(true);
+      break;
+    case 'x':
+      flag_x = true;
+      break;
+    case 1:
+      // -x swallows all following arguments, so we use '-' in the getopt
+      // string and collect files here.
+      if (!archive_name) {
+        archive_name = optarg;
+      } else if (flag_x) {
+        excludes.insert(optarg);
+      } else {
+        includes.insert(optarg);
+      }
+      break;
+    default:
+      ShowHelp(false);
+      break;
+  }
+}
+
+int main(int argc, char* argv[]) {
+  // Who am I, and what am I doing?
+  g_progname = basename(argv[0]);
+  if (!strcmp(g_progname, "ziptool") && argc > 1) return main(argc - 1, argv + 1);
+  if (!strcmp(g_progname, "unzip")) {
+    role = kUnzip;
+  } else if (!strcmp(g_progname, "zipinfo")) {
+    role = kZipinfo;
+  } else {
+    die(0, "run as ziptool with unzip or zipinfo as the first argument, or symlink");
+  }
+
+  static const struct option opts[] = {
+      {"help", no_argument, 0, 'h'},
+      {},
+  };
+
+  if (role == kUnzip) {
+    // `unzip -Z` is "zipinfo mode", so in that case just restart...
+    if (argc > 1 && !strcmp(argv[1], "-Z")) {
+      argv[1] = const_cast<char*>("zipinfo");
+      return main(argc - 1, argv + 1);
+    }
+
+    int opt;
+    while ((opt = getopt_long(argc, argv, "-d:hlnopqvx", opts, nullptr)) != -1) {
+      switch (opt) {
+        case 'd':
+          flag_d = optarg;
+          if (!EndsWith(flag_d, "/")) flag_d += '/';
+          break;
+        case 'l':
+          flag_l = true;
+          break;
+        case 'n':
+          overwrite_mode = kNever;
+          break;
+        case 'o':
+          overwrite_mode = kAlways;
+          break;
+        case 'p':
+          flag_p = flag_q = true;
+          break;
+        case 'q':
+          flag_q = true;
+          break;
+        case 'v':
+          flag_v = true;
+          break;
+        default:
+          HandleCommonOption(opt);
+          break;
+      }
+    }
+  } else {
+    int opt;
+    while ((opt = getopt_long(argc, argv, "-1hx", opts, nullptr)) != -1) {
+      switch (opt) {
+        case '1':
+          flag_1 = true;
+          break;
+        default:
+          HandleCommonOption(opt);
+          break;
+      }
+    }
+  }
+
+  if (!archive_name) die(0, "missing archive filename");
+
+  // We can't support "-" to unzip from stdin because libziparchive relies on mmap.
+  ZipArchiveHandle zah;
+  int32_t err;
+  if ((err = OpenArchive(archive_name, &zah)) != 0) {
+    die(0, "couldn't open %s: %s", archive_name, ErrorCodeString(err));
+  }
+
+  // Implement -d by changing into that directory.
+  // We'll create implicit directories based on paths in the zip file, and we'll create
+  // the -d directory itself, but we require that *parents* of the -d directory already exists.
+  // This is pretty arbitrary, but it's the behavior of the original unzip.
+  if (!flag_d.empty()) {
+    if (mkdir(flag_d.c_str(), 0777) == -1 && errno != EEXIST) {
+      die(errno, "couldn't created %s", flag_d.c_str());
+    }
+    if (chdir(flag_d.c_str()) == -1) {
+      die(errno, "couldn't chdir to %s", flag_d.c_str());
+    }
+  }
+
+  ProcessAll(zah);
+
+  CloseArchive(zah);
+  return 0;
+}
diff --git a/lmkd/Android.bp b/lmkd/Android.bp
deleted file mode 100644
index 4c5ca03..0000000
--- a/lmkd/Android.bp
+++ /dev/null
@@ -1,53 +0,0 @@
-cc_binary {
-    name: "lmkd",
-
-    srcs: ["lmkd.c"],
-    shared_libs: [
-        "libcutils",
-        "liblog",
-        "libprocessgroup",
-        "libpsi",
-    ],
-    static_libs: [
-        "libstatslogc",
-        "libstatssocket",
-    ],
-    local_include_dirs: ["include"],
-    cflags: ["-Werror", "-DLMKD_TRACE_KILLS"],
-    init_rc: ["lmkd.rc"],
-    product_variables: {
-        use_lmkd_stats_log: {
-            cflags: [
-                "-DLMKD_LOG_STATS"
-            ],
-        },
-    },
-    logtags: ["event.logtags"],
-}
-
-cc_library_static {
-    name: "libstatslogc",
-    srcs: ["statslog.c"],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    shared_libs: [
-        "liblog",
-    ],
-    static_libs: ["libstatssocket",],
-}
-
-cc_library_static {
-    name: "liblmkd_utils",
-    srcs: ["liblmkd_utils.c"],
-    shared_libs: [
-        "libcutils",
-    ],
-    export_include_dirs: ["include"],
-    cppflags: [
-        "-g",
-        "-Wall",
-        "-Werror",
-    ]
-}
diff --git a/lmkd/OWNERS b/lmkd/OWNERS
deleted file mode 100644
index b15bb48..0000000
--- a/lmkd/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-surenb@google.com
diff --git a/lmkd/README.md b/lmkd/README.md
deleted file mode 100644
index 656a6ea..0000000
--- a/lmkd/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-Android Low Memory Killer Daemon
-================================
-
-
-Introduction
-------------
-
-Android Low Memory Killer Daemon (lmkd) is a process monitoring memory
-state of a running Android system and reacting to high memory pressure
-by killing the least essential process(es) to keep system performing
-at acceptable levels.
-
-
-Background
-----------
-
-Historically on Android systems memory monitoring and killing of
-non-essential processes was handled by a kernel lowmemorykiller driver.
-Since Linux Kernel 4.12 the lowmemorykiller driver has been removed and
-instead userspace lmkd daemon performs these tasks.
-
-
-Android Properties
-------------------
-
-lmkd can be configured on a particular system using the following Android
-properties:
-
-  ro.config.low_ram:         choose between low-memory vs high-performance
-                             device. Default = false.
-
-  ro.lmk.use_minfree_levels: use free memory and file cache thresholds for
-                             making decisions when to kill. This mode works
-                             the same way kernel lowmemorykiller driver used
-                             to work. Default = false
-
-  ro.lmk.low:                min oom_adj score for processes eligible to be
-                             killed at low vmpressure level. Default = 1001
-                             (disabled)
-
-  ro.lmk.medium:             min oom_adj score for processes eligible to be
-                             killed at medium vmpressure level. Default = 800
-                             (non-essential processes)
-
-  ro.lmk.critical:           min oom_adj score for processes eligible to be
-                             killed at critical vmpressure level. Default = 0
-                             (all processes)
-
-  ro.lmk.critical_upgrade:   enables upgrade to critical level. Default = false
-
-  ro.lmk.upgrade_pressure:   max mem_pressure at which level will be upgraded
-                             because system is swapping too much. Default = 100
-                             (disabled)
-
-  ro.lmk.downgrade_pressure: min mem_pressure at which vmpressure event will
-                             be ignored because enough free memory is still
-                             available. Default = 100 (disabled)
-
-  ro.lmk.kill_heaviest_task: kill heaviest eligible task (best decision) vs.
-                             any eligible task (fast decision). Default = false
-
-  ro.lmk.kill_timeout_ms:    duration in ms after a kill when no additional
-                             kill will be done, Default = 0 (disabled)
-
-  ro.lmk.debug:              enable lmkd debug logs, Default = false
diff --git a/lmkd/event.logtags b/lmkd/event.logtags
deleted file mode 100644
index 065c6db..0000000
--- a/lmkd/event.logtags
+++ /dev/null
@@ -1,38 +0,0 @@
-# The entries in this file map a sparse set of log tag numbers to tag names.
-# This is installed on the device, in /system/etc, and parsed by logcat.
-#
-# Tag numbers are decimal integers, from 0 to 2^31.  (Let's leave the
-# negative values alone for now.)
-#
-# Tag names are one or more ASCII letters and numbers or underscores, i.e.
-# "[A-Z][a-z][0-9]_".  Do not include spaces or punctuation (the former
-# impacts log readability, the latter makes regex searches more annoying).
-#
-# Tag numbers and names are separated by whitespace.  Blank lines and lines
-# starting with '#' are ignored.
-#
-# Optionally, after the tag names can be put a description for the value(s)
-# of the tag. Description are in the format
-#    (<name>|data type[|data unit])
-# Multiple values are separated by commas.
-#
-# The data type is a number from the following values:
-# 1: int
-# 2: long
-# 3: string
-# 4: list
-#
-# The data unit is a number taken from the following list:
-# 1: Number of objects
-# 2: Number of bytes
-# 3: Number of milliseconds
-# 4: Number of allocations
-# 5: Id
-# 6: Percent
-# s: Number of seconds (monotonic time)
-# Default value for data of type int/long is 2 (bytes).
-#
-# TODO: generate ".java" and ".h" files with integer constants from this file.
-
-# for meminfo logs
-10195355 meminfo (MemFree|1),(Cached|1),(SwapCached|1),(Buffers|1),(Shmem|1),(Unevictable|1),(SwapTotal|1),(SwapFree|1),(ActiveAnon|1),(InactiveAnon|1),(ActiveFile|1),(InactiveFile|1),(SReclaimable|1),(SUnreclaim|1),(KernelStack|1),(PageTables|1),(ION_heap|1),(ION_heap_pool|1),(CmaFree|1)
diff --git a/lmkd/include/liblmkd_utils.h b/lmkd/include/liblmkd_utils.h
deleted file mode 100644
index 72e3f4a..0000000
--- a/lmkd/include/liblmkd_utils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Copyright 2018 Google, Inc
- *
- *  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 _LIBLMKD_UTILS_H_
-#define _LIBLMKD_UTILS_H_
-
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-#include <lmkd.h>
-
-__BEGIN_DECLS
-
-/*
- * Connects to lmkd process and returns socket handle.
- * On success returns socket handle.
- * On error, -1 is returned, and errno is set appropriately.
- */
-int lmkd_connect();
-
-/*
- * Registers a process with lmkd and sets its oomadj score.
- * On success returns 0.
- * On error, -1 is returned.
- * In the case of error errno is set appropriately.
- */
-int lmkd_register_proc(int sock, struct lmk_procprio *params);
-
-/*
- * Creates memcg directory for given process.
- * On success returns 0.
- * -1 is returned if path creation failed.
- * -2 is returned if tasks file open operation failed.
- * -3 is returned if tasks file write operation failed.
- * In the case of error errno is set appropriately.
- */
-int create_memcg(uid_t uid, pid_t pid);
-
-__END_DECLS
-
-#endif /* _LIBLMKD_UTILS_H_ */
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h
deleted file mode 100644
index 59377dd..0000000
--- a/lmkd/include/lmkd.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *  Copyright 2018 Google, Inc
- *
- *  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 _LMKD_H_
-#define _LMKD_H_
-
-#include <arpa/inet.h>
-#include <sys/cdefs.h>
-#include <sys/types.h>
-
-__BEGIN_DECLS
-
-/*
- * Supported LMKD commands
- */
-enum lmk_cmd {
-    LMK_TARGET = 0,  /* Associate minfree with oom_adj_score */
-    LMK_PROCPRIO,    /* Register a process and set its oom_adj_score */
-    LMK_PROCREMOVE,  /* Unregister a process */
-    LMK_PROCPURGE,   /* Purge all registered processes */
-    LMK_GETKILLCNT,  /* Get number of kills */
-};
-
-/*
- * Max number of targets in LMK_TARGET command.
- */
-#define MAX_TARGETS 6
-
-/*
- * Max packet length in bytes.
- * Longest packet is LMK_TARGET followed by MAX_TARGETS
- * of minfree and oom_adj_score values
- */
-#define CTRL_PACKET_MAX_SIZE (sizeof(int) * (MAX_TARGETS * 2 + 1))
-
-/* LMKD packet - first int is lmk_cmd followed by payload */
-typedef int LMKD_CTRL_PACKET[CTRL_PACKET_MAX_SIZE / sizeof(int)];
-
-/* Get LMKD packet command */
-static inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) {
-    return (enum lmk_cmd)ntohl(pack[0]);
-}
-
-/* LMK_TARGET packet payload */
-struct lmk_target {
-    int minfree;
-    int oom_adj_score;
-};
-
-/*
- * For LMK_TARGET packet get target_idx-th payload.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet, int target_idx,
-                                        struct lmk_target* target) {
-    target->minfree = ntohl(packet[target_idx * 2 + 1]);
-    target->oom_adj_score = ntohl(packet[target_idx * 2 + 2]);
-}
-
-/*
- * Prepare LMK_TARGET packet and return packet size in bytes.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet, struct lmk_target* targets,
-                                          size_t target_cnt) {
-    int idx = 0;
-    packet[idx++] = htonl(LMK_TARGET);
-    while (target_cnt) {
-        packet[idx++] = htonl(targets->minfree);
-        packet[idx++] = htonl(targets->oom_adj_score);
-        targets++;
-        target_cnt--;
-    }
-    return idx * sizeof(int);
-}
-
-/* LMK_PROCPRIO packet payload */
-struct lmk_procprio {
-    pid_t pid;
-    uid_t uid;
-    int oomadj;
-};
-
-/*
- * For LMK_PROCPRIO packet get its payload.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
-    params->pid = (pid_t)ntohl(packet[1]);
-    params->uid = (uid_t)ntohl(packet[2]);
-    params->oomadj = ntohl(packet[3]);
-}
-
-/*
- * Prepare LMK_PROCPRIO packet and return packet size in bytes.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
-    packet[0] = htonl(LMK_PROCPRIO);
-    packet[1] = htonl(params->pid);
-    packet[2] = htonl(params->uid);
-    packet[3] = htonl(params->oomadj);
-    return 4 * sizeof(int);
-}
-
-/* LMK_PROCREMOVE packet payload */
-struct lmk_procremove {
-    pid_t pid;
-};
-
-/*
- * For LMK_PROCREMOVE packet get its payload.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,
-                                            struct lmk_procremove* params) {
-    params->pid = (pid_t)ntohl(packet[1]);
-}
-
-/*
- * Prepare LMK_PROCREMOVE packet and return packet size in bytes.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
-                                              struct lmk_procprio* params) {
-    packet[0] = htonl(LMK_PROCREMOVE);
-    packet[1] = htonl(params->pid);
-    return 2 * sizeof(int);
-}
-
-/*
- * Prepare LMK_PROCPURGE packet and return packet size in bytes.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
-    packet[0] = htonl(LMK_PROCPURGE);
-    return sizeof(int);
-}
-
-/* LMK_GETKILLCNT packet payload */
-struct lmk_getkillcnt {
-    int min_oomadj;
-    int max_oomadj;
-};
-
-/*
- * For LMK_GETKILLCNT packet get its payload.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
-                                            struct lmk_getkillcnt* params) {
-    params->min_oomadj = ntohl(packet[1]);
-    params->max_oomadj = ntohl(packet[2]);
-}
-
-/*
- * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
-                                              struct lmk_getkillcnt* params) {
-    packet[0] = htonl(LMK_GETKILLCNT);
-    packet[1] = htonl(params->min_oomadj);
-    packet[2] = htonl(params->max_oomadj);
-    return 3 * sizeof(int);
-}
-
-/*
- * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
- * Warning: no checks performed, caller should ensure valid parameters.
- */
-static inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
-    packet[0] = htonl(LMK_GETKILLCNT);
-    packet[1] = htonl(kill_cnt);
-    return 2 * sizeof(int);
-}
-
-__END_DECLS
-
-#endif /* _LMKD_H_ */
diff --git a/lmkd/liblmkd_utils.c b/lmkd/liblmkd_utils.c
deleted file mode 100644
index fa3b7a9..0000000
--- a/lmkd/liblmkd_utils.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  Copyright 2018 Google, Inc
- *
- *  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 <errno.h>
-#include <fcntl.h>
-#include <sys/cdefs.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <liblmkd_utils.h>
-#include <cutils/sockets.h>
-
-int lmkd_connect() {
-    return socket_local_client("lmkd",
-                               ANDROID_SOCKET_NAMESPACE_RESERVED,
-                               SOCK_SEQPACKET);
-}
-
-int lmkd_register_proc(int sock, struct lmk_procprio *params) {
-    LMKD_CTRL_PACKET packet;
-    size_t size;
-    int ret;
-
-    size = lmkd_pack_set_procprio(packet, params);
-    ret = TEMP_FAILURE_RETRY(write(sock, packet, size));
-
-    return (ret < 0) ? -1 : 0;
-}
-
-int create_memcg(uid_t uid, pid_t pid) {
-    char buf[256];
-    int tasks_file;
-    int written;
-
-    snprintf(buf, sizeof(buf), "/dev/memcg/apps/uid_%u", uid);
-    if (mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 &&
-        errno != EEXIST) {
-        return -1;
-    }
-
-    snprintf(buf, sizeof(buf), "/dev/memcg/apps/uid_%u/pid_%u", uid, pid);
-    if (mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 &&
-        errno != EEXIST) {
-        return -1;
-    }
-
-    snprintf(buf, sizeof(buf), "/dev/memcg/apps/uid_%u/pid_%u/tasks", uid, pid);
-    tasks_file = open(buf, O_WRONLY);
-    if (tasks_file < 0) {
-        return -2;
-    }
-    written = snprintf(buf, sizeof(buf), "%u", pid);
-    if (__predict_false(written >= (int)sizeof(buf))) {
-        written = sizeof(buf) - 1;
-    }
-    written = TEMP_FAILURE_RETRY(write(tasks_file, buf, written));
-    close(tasks_file);
-
-    return (written < 0) ? -3 : 0;
-}
-
diff --git a/lmkd/libpsi/Android.bp b/lmkd/libpsi/Android.bp
deleted file mode 100644
index 8a97094..0000000
--- a/lmkd/libpsi/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-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
deleted file mode 100644
index b15bb48..0000000
--- a/lmkd/libpsi/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-surenb@google.com
diff --git a/lmkd/libpsi/include/psi/psi.h b/lmkd/libpsi/include/psi/psi.h
deleted file mode 100644
index cd49e8b..0000000
--- a/lmkd/libpsi/include/psi/psi.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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
deleted file mode 100644
index f4d5d18..0000000
--- a/lmkd/libpsi/psi.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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/lmkd/lmkd.c b/lmkd/lmkd.c
deleted file mode 100644
index 7c5a466..0000000
--- a/lmkd/lmkd.c
+++ /dev/null
@@ -1,2159 +0,0 @@
-/*
- * Copyright (C) 2013 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 "lowmemorykiller"
-
-#include <dirent.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <pwd.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/cdefs.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/sysinfo.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <cutils/sched_policy.h>
-#include <cutils/sockets.h>
-#include <lmkd.h>
-#include <log/log.h>
-#include <log/log_event_list.h>
-#include <log/log_time.h>
-#include <psi/psi.h>
-#include <system/thread_defs.h>
-
-#ifdef LMKD_LOG_STATS
-#include "statslog.h"
-#endif
-
-/*
- * Define LMKD_TRACE_KILLS to record lmkd kills in kernel traces
- * to profile and correlate with OOM kills
- */
-#ifdef LMKD_TRACE_KILLS
-
-#define ATRACE_TAG ATRACE_TAG_ALWAYS
-#include <cutils/trace.h>
-
-#define TRACE_KILL_START(pid) ATRACE_INT(__FUNCTION__, pid);
-#define TRACE_KILL_END()      ATRACE_INT(__FUNCTION__, 0);
-
-#else /* LMKD_TRACE_KILLS */
-
-#define TRACE_KILL_START(pid) ((void)(pid))
-#define TRACE_KILL_END() ((void)0)
-
-#endif /* LMKD_TRACE_KILLS */
-
-#ifndef __unused
-#define __unused __attribute__((__unused__))
-#endif
-
-#define MEMCG_SYSFS_PATH "/dev/memcg/"
-#define MEMCG_MEMORY_USAGE "/dev/memcg/memory.usage_in_bytes"
-#define MEMCG_MEMORYSW_USAGE "/dev/memcg/memory.memsw.usage_in_bytes"
-#define ZONEINFO_PATH "/proc/zoneinfo"
-#define MEMINFO_PATH "/proc/meminfo"
-#define PROC_STATUS_TGID_FIELD "Tgid:"
-#define LINE_MAX 128
-
-/* Android Logger event logtags (see event.logtags) */
-#define MEMINFO_LOG_TAG 10195355
-
-/* gid containing AID_SYSTEM required */
-#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
-#define INKERNEL_ADJ_PATH "/sys/module/lowmemorykiller/parameters/adj"
-
-#define ARRAY_SIZE(x)   (sizeof(x) / sizeof(*(x)))
-#define EIGHT_MEGA (1 << 23)
-
-#define TARGET_UPDATE_MIN_INTERVAL_MS 1000
-
-#define NS_PER_MS (NS_PER_SEC / MS_PER_SEC)
-#define US_PER_MS (US_PER_SEC / MS_PER_SEC)
-
-/* Defined as ProcessList.SYSTEM_ADJ in ProcessList.java */
-#define SYSTEM_ADJ (-900)
-
-#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
-#define STRINGIFY_INTERNAL(x) #x
-
-/*
- * PSI monitor tracking window size.
- * PSI monitor generates events at most once per window,
- * therefore we poll memory state for the duration of
- * PSI_WINDOW_SIZE_MS after the event happens.
- */
-#define PSI_WINDOW_SIZE_MS 1000
-/* Polling period after initial PSI signal */
-#define PSI_POLL_PERIOD_MS 10
-/* Poll for the duration of one window after initial PSI signal */
-#define PSI_POLL_COUNT (PSI_WINDOW_SIZE_MS / PSI_POLL_PERIOD_MS)
-
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-
-#define FAIL_REPORT_RLIMIT_MS 1000
-
-/* default to old in-kernel interface if no memory pressure events */
-static bool use_inkernel_interface = true;
-static bool has_inkernel_module;
-
-/* memory pressure levels */
-enum vmpressure_level {
-    VMPRESS_LEVEL_LOW = 0,
-    VMPRESS_LEVEL_MEDIUM,
-    VMPRESS_LEVEL_CRITICAL,
-    VMPRESS_LEVEL_COUNT
-};
-
-static const char *level_name[] = {
-    "low",
-    "medium",
-    "critical"
-};
-
-struct {
-    int64_t min_nr_free_pages; /* recorded but not used yet */
-    int64_t max_nr_free_pages;
-} low_pressure_mem = { -1, -1 };
-
-struct psi_threshold {
-    enum psi_stall_type stall_type;
-    int threshold_ms;
-};
-
-static int level_oomadj[VMPRESS_LEVEL_COUNT];
-static int mpevfd[VMPRESS_LEVEL_COUNT] = { -1, -1, -1 };
-static bool debug_process_killing;
-static bool enable_pressure_upgrade;
-static int64_t upgrade_pressure;
-static int64_t downgrade_pressure;
-static bool low_ram_device;
-static bool kill_heaviest_task;
-static unsigned long kill_timeout_ms;
-static bool use_minfree_levels;
-static bool per_app_memcg;
-static int swap_free_low_percentage;
-static bool use_psi_monitors = false;
-static struct psi_threshold psi_thresholds[VMPRESS_LEVEL_COUNT] = {
-    { PSI_SOME, 70 },    /* 70ms out of 1sec for partial stall */
-    { PSI_SOME, 100 },   /* 100ms out of 1sec for partial stall */
-    { PSI_FULL, 70 },    /* 70ms out of 1sec for complete stall */
-};
-
-static android_log_context ctx;
-
-/* data required to handle events */
-struct event_handler_info {
-    int data;
-    void (*handler)(int data, uint32_t events);
-};
-
-/* data required to handle socket events */
-struct sock_event_handler_info {
-    int sock;
-    struct event_handler_info handler_info;
-};
-
-/* max supported number of data connections */
-#define MAX_DATA_CONN 2
-
-/* socket event handler data */
-static struct sock_event_handler_info ctrl_sock;
-static struct sock_event_handler_info data_sock[MAX_DATA_CONN];
-
-/* vmpressure event handler data */
-static struct event_handler_info vmpressure_hinfo[VMPRESS_LEVEL_COUNT];
-
-/* 3 memory pressure levels, 1 ctrl listen socket, 2 ctrl data socket */
-#define MAX_EPOLL_EVENTS (1 + MAX_DATA_CONN + VMPRESS_LEVEL_COUNT)
-static int epollfd;
-static int maxevents;
-
-/* OOM score values used by both kernel and framework */
-#define OOM_SCORE_ADJ_MIN       (-1000)
-#define OOM_SCORE_ADJ_MAX       1000
-
-static int lowmem_adj[MAX_TARGETS];
-static int lowmem_minfree[MAX_TARGETS];
-static int lowmem_targets_size;
-
-/* Fields to parse in /proc/zoneinfo */
-enum zoneinfo_field {
-    ZI_NR_FREE_PAGES = 0,
-    ZI_NR_FILE_PAGES,
-    ZI_NR_SHMEM,
-    ZI_NR_UNEVICTABLE,
-    ZI_WORKINGSET_REFAULT,
-    ZI_HIGH,
-    ZI_FIELD_COUNT
-};
-
-static const char* const zoneinfo_field_names[ZI_FIELD_COUNT] = {
-    "nr_free_pages",
-    "nr_file_pages",
-    "nr_shmem",
-    "nr_unevictable",
-    "workingset_refault",
-    "high",
-};
-
-union zoneinfo {
-    struct {
-        int64_t nr_free_pages;
-        int64_t nr_file_pages;
-        int64_t nr_shmem;
-        int64_t nr_unevictable;
-        int64_t workingset_refault;
-        int64_t high;
-        /* fields below are calculated rather than read from the file */
-        int64_t totalreserve_pages;
-    } field;
-    int64_t arr[ZI_FIELD_COUNT];
-};
-
-/* Fields to parse in /proc/meminfo */
-enum meminfo_field {
-    MI_NR_FREE_PAGES = 0,
-    MI_CACHED,
-    MI_SWAP_CACHED,
-    MI_BUFFERS,
-    MI_SHMEM,
-    MI_UNEVICTABLE,
-    MI_TOTAL_SWAP,
-    MI_FREE_SWAP,
-    MI_ACTIVE_ANON,
-    MI_INACTIVE_ANON,
-    MI_ACTIVE_FILE,
-    MI_INACTIVE_FILE,
-    MI_SRECLAIMABLE,
-    MI_SUNRECLAIM,
-    MI_KERNEL_STACK,
-    MI_PAGE_TABLES,
-    MI_ION_HELP,
-    MI_ION_HELP_POOL,
-    MI_CMA_FREE,
-    MI_FIELD_COUNT
-};
-
-static const char* const meminfo_field_names[MI_FIELD_COUNT] = {
-    "MemFree:",
-    "Cached:",
-    "SwapCached:",
-    "Buffers:",
-    "Shmem:",
-    "Unevictable:",
-    "SwapTotal:",
-    "SwapFree:",
-    "Active(anon):",
-    "Inactive(anon):",
-    "Active(file):",
-    "Inactive(file):",
-    "SReclaimable:",
-    "SUnreclaim:",
-    "KernelStack:",
-    "PageTables:",
-    "ION_heap:",
-    "ION_heap_pool:",
-    "CmaFree:",
-};
-
-union meminfo {
-    struct {
-        int64_t nr_free_pages;
-        int64_t cached;
-        int64_t swap_cached;
-        int64_t buffers;
-        int64_t shmem;
-        int64_t unevictable;
-        int64_t total_swap;
-        int64_t free_swap;
-        int64_t active_anon;
-        int64_t inactive_anon;
-        int64_t active_file;
-        int64_t inactive_file;
-        int64_t sreclaimable;
-        int64_t sunreclaimable;
-        int64_t kernel_stack;
-        int64_t page_tables;
-        int64_t ion_heap;
-        int64_t ion_heap_pool;
-        int64_t cma_free;
-        /* fields below are calculated rather than read from the file */
-        int64_t nr_file_pages;
-    } field;
-    int64_t arr[MI_FIELD_COUNT];
-};
-
-enum field_match_result {
-    NO_MATCH,
-    PARSE_FAIL,
-    PARSE_SUCCESS
-};
-
-struct adjslot_list {
-    struct adjslot_list *next;
-    struct adjslot_list *prev;
-};
-
-struct proc {
-    struct adjslot_list asl;
-    int pid;
-    uid_t uid;
-    int oomadj;
-    struct proc *pidhash_next;
-};
-
-struct reread_data {
-    const char* const filename;
-    int fd;
-};
-
-#ifdef LMKD_LOG_STATS
-static bool enable_stats_log;
-static android_log_context log_ctx;
-#endif
-
-#define PIDHASH_SZ 1024
-static struct proc *pidhash[PIDHASH_SZ];
-#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
-
-#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
-#define ADJTOSLOT_COUNT (ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1)
-static struct adjslot_list procadjslot_list[ADJTOSLOT_COUNT];
-
-#define MAX_DISTINCT_OOM_ADJ 32
-#define KILLCNT_INVALID_IDX 0xFF
-/*
- * Because killcnt array is sparse a two-level indirection is used
- * to keep the size small. killcnt_idx stores index of the element in
- * killcnt array. Index KILLCNT_INVALID_IDX indicates an unused slot.
- */
-static uint8_t killcnt_idx[ADJTOSLOT_COUNT];
-static uint16_t killcnt[MAX_DISTINCT_OOM_ADJ];
-static int killcnt_free_idx = 0;
-static uint32_t killcnt_total = 0;
-
-/* PAGE_SIZE / 1024 */
-static long page_k;
-
-static bool parse_int64(const char* str, int64_t* ret) {
-    char* endptr;
-    long long val = strtoll(str, &endptr, 10);
-    if (str == endptr || val > INT64_MAX) {
-        return false;
-    }
-    *ret = (int64_t)val;
-    return true;
-}
-
-static enum field_match_result match_field(const char* cp, const char* ap,
-                                   const char* const field_names[],
-                                   int field_count, int64_t* field,
-                                   int *field_idx) {
-    int64_t val;
-    int i;
-
-    for (i = 0; i < field_count; i++) {
-        if (!strcmp(cp, field_names[i])) {
-            *field_idx = i;
-            return parse_int64(ap, field) ? PARSE_SUCCESS : PARSE_FAIL;
-        }
-    }
-    return NO_MATCH;
-}
-
-/*
- * Read file content from the beginning up to max_len bytes or EOF
- * whichever happens first.
- */
-static ssize_t read_all(int fd, char *buf, size_t max_len)
-{
-    ssize_t ret = 0;
-    off_t offset = 0;
-
-    while (max_len > 0) {
-        ssize_t r = TEMP_FAILURE_RETRY(pread(fd, buf, max_len, offset));
-        if (r == 0) {
-            break;
-        }
-        if (r == -1) {
-            return -1;
-        }
-        ret += r;
-        buf += r;
-        offset += r;
-        max_len -= r;
-    }
-
-    return ret;
-}
-
-/*
- * Read a new or already opened file from the beginning.
- * If the file has not been opened yet data->fd should be set to -1.
- * To be used with files which are read often and possibly during high
- * memory pressure to minimize file opening which by itself requires kernel
- * memory allocation and might result in a stall on memory stressed system.
- */
-static int reread_file(struct reread_data *data, char *buf, size_t buf_size) {
-    ssize_t size;
-
-    if (data->fd == -1) {
-        data->fd = open(data->filename, O_RDONLY | O_CLOEXEC);
-        if (data->fd == -1) {
-            ALOGE("%s open: %s", data->filename, strerror(errno));
-            return -1;
-        }
-    }
-
-    size = read_all(data->fd, buf, buf_size - 1);
-    if (size < 0) {
-        ALOGE("%s read: %s", data->filename, strerror(errno));
-        close(data->fd);
-        data->fd = -1;
-        return -1;
-    }
-    ALOG_ASSERT((size_t)size < buf_size - 1, "%s too large", data->filename);
-    buf[size] = 0;
-
-    return 0;
-}
-
-static struct proc *pid_lookup(int pid) {
-    struct proc *procp;
-
-    for (procp = pidhash[pid_hashfn(pid)]; procp && procp->pid != pid;
-         procp = procp->pidhash_next)
-            ;
-
-    return procp;
-}
-
-static void adjslot_insert(struct adjslot_list *head, struct adjslot_list *new)
-{
-    struct adjslot_list *next = head->next;
-    new->prev = head;
-    new->next = next;
-    next->prev = new;
-    head->next = new;
-}
-
-static void adjslot_remove(struct adjslot_list *old)
-{
-    struct adjslot_list *prev = old->prev;
-    struct adjslot_list *next = old->next;
-    next->prev = prev;
-    prev->next = next;
-}
-
-static struct adjslot_list *adjslot_tail(struct adjslot_list *head) {
-    struct adjslot_list *asl = head->prev;
-
-    return asl == head ? NULL : asl;
-}
-
-static void proc_slot(struct proc *procp) {
-    int adjslot = ADJTOSLOT(procp->oomadj);
-
-    adjslot_insert(&procadjslot_list[adjslot], &procp->asl);
-}
-
-static void proc_unslot(struct proc *procp) {
-    adjslot_remove(&procp->asl);
-}
-
-static void proc_insert(struct proc *procp) {
-    int hval = pid_hashfn(procp->pid);
-
-    procp->pidhash_next = pidhash[hval];
-    pidhash[hval] = procp;
-    proc_slot(procp);
-}
-
-static int pid_remove(int pid) {
-    int hval = pid_hashfn(pid);
-    struct proc *procp;
-    struct proc *prevp;
-
-    for (procp = pidhash[hval], prevp = NULL; procp && procp->pid != pid;
-         procp = procp->pidhash_next)
-            prevp = procp;
-
-    if (!procp)
-        return -1;
-
-    if (!prevp)
-        pidhash[hval] = procp->pidhash_next;
-    else
-        prevp->pidhash_next = procp->pidhash_next;
-
-    proc_unslot(procp);
-    free(procp);
-    return 0;
-}
-
-/*
- * Write a string to a file.
- * Returns false if the file does not exist.
- */
-static bool writefilestring(const char *path, const char *s,
-                            bool err_if_missing) {
-    int fd = open(path, O_WRONLY | O_CLOEXEC);
-    ssize_t len = strlen(s);
-    ssize_t ret;
-
-    if (fd < 0) {
-        if (err_if_missing) {
-            ALOGE("Error opening %s; errno=%d", path, errno);
-        }
-        return false;
-    }
-
-    ret = TEMP_FAILURE_RETRY(write(fd, s, len));
-    if (ret < 0) {
-        ALOGE("Error writing %s; errno=%d", path, errno);
-    } else if (ret < len) {
-        ALOGE("Short write on %s; length=%zd", path, ret);
-    }
-
-    close(fd);
-    return true;
-}
-
-static inline long get_time_diff_ms(struct timespec *from,
-                                    struct timespec *to) {
-    return (to->tv_sec - from->tv_sec) * (long)MS_PER_SEC +
-           (to->tv_nsec - from->tv_nsec) / (long)NS_PER_MS;
-}
-
-static int proc_get_tgid(int pid) {
-    char path[PATH_MAX];
-    char buf[PAGE_SIZE];
-    int fd;
-    ssize_t size;
-    char *pos;
-    int64_t tgid = -1;
-
-    snprintf(path, PATH_MAX, "/proc/%d/status", pid);
-    fd = open(path, O_RDONLY | O_CLOEXEC);
-    if (fd < 0) {
-        return -1;
-    }
-
-    size = read_all(fd, buf, sizeof(buf) - 1);
-    if (size < 0) {
-        goto out;
-    }
-    buf[size] = 0;
-
-    pos = buf;
-    while (true) {
-        pos = strstr(pos, PROC_STATUS_TGID_FIELD);
-        /* Stop if TGID tag not found or found at the line beginning */
-        if (pos == NULL || pos == buf || pos[-1] == '\n') {
-            break;
-        }
-        pos++;
-    }
-
-    if (pos == NULL) {
-        goto out;
-    }
-
-    pos += strlen(PROC_STATUS_TGID_FIELD);
-    while (*pos == ' ') pos++;
-    parse_int64(pos, &tgid);
-
-out:
-    close(fd);
-    return (int)tgid;
-}
-
-static void cmd_procprio(LMKD_CTRL_PACKET packet) {
-    struct proc *procp;
-    char path[80];
-    char val[20];
-    int soft_limit_mult;
-    struct lmk_procprio params;
-    bool is_system_server;
-    struct passwd *pwdrec;
-    int tgid;
-
-    lmkd_pack_get_procprio(packet, &params);
-
-    if (params.oomadj < OOM_SCORE_ADJ_MIN ||
-        params.oomadj > OOM_SCORE_ADJ_MAX) {
-        ALOGE("Invalid PROCPRIO oomadj argument %d", params.oomadj);
-        return;
-    }
-
-    /* Check if registered process is a thread group leader */
-    tgid = proc_get_tgid(params.pid);
-    if (tgid >= 0 && tgid != params.pid) {
-        ALOGE("Attempt to register a task that is not a thread group leader (tid %d, tgid %d)",
-            params.pid, tgid);
-        return;
-    }
-
-    /* gid containing AID_READPROC required */
-    /* CAP_SYS_RESOURCE required */
-    /* CAP_DAC_OVERRIDE required */
-    snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid);
-    snprintf(val, sizeof(val), "%d", params.oomadj);
-    if (!writefilestring(path, val, false)) {
-        ALOGW("Failed to open %s; errno=%d: process %d might have been killed",
-              path, errno, params.pid);
-        /* If this file does not exist the process is dead. */
-        return;
-    }
-
-    if (use_inkernel_interface) {
-        return;
-    }
-
-    if (per_app_memcg) {
-        if (params.oomadj >= 900) {
-            soft_limit_mult = 0;
-        } else if (params.oomadj >= 800) {
-            soft_limit_mult = 0;
-        } else if (params.oomadj >= 700) {
-            soft_limit_mult = 0;
-        } else if (params.oomadj >= 600) {
-            // Launcher should be perceptible, don't kill it.
-            params.oomadj = 200;
-            soft_limit_mult = 1;
-        } else if (params.oomadj >= 500) {
-            soft_limit_mult = 0;
-        } else if (params.oomadj >= 400) {
-            soft_limit_mult = 0;
-        } else if (params.oomadj >= 300) {
-            soft_limit_mult = 1;
-        } else if (params.oomadj >= 200) {
-            soft_limit_mult = 8;
-        } else if (params.oomadj >= 100) {
-            soft_limit_mult = 10;
-        } else if (params.oomadj >=   0) {
-            soft_limit_mult = 20;
-        } else {
-            // Persistent processes will have a large
-            // soft limit 512MB.
-            soft_limit_mult = 64;
-        }
-
-        snprintf(path, sizeof(path), MEMCG_SYSFS_PATH
-                 "apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
-                 params.uid, params.pid);
-        snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
-
-        /*
-         * system_server process has no memcg under /dev/memcg/apps but should be
-         * registered with lmkd. This is the best way so far to identify it.
-         */
-        is_system_server = (params.oomadj == SYSTEM_ADJ &&
-                            (pwdrec = getpwnam("system")) != NULL &&
-                            params.uid == pwdrec->pw_uid);
-        writefilestring(path, val, !is_system_server);
-    }
-
-    procp = pid_lookup(params.pid);
-    if (!procp) {
-            procp = malloc(sizeof(struct proc));
-            if (!procp) {
-                // Oh, the irony.  May need to rebuild our state.
-                return;
-            }
-
-            procp->pid = params.pid;
-            procp->uid = params.uid;
-            procp->oomadj = params.oomadj;
-            proc_insert(procp);
-    } else {
-        proc_unslot(procp);
-        procp->oomadj = params.oomadj;
-        proc_slot(procp);
-    }
-}
-
-static void cmd_procremove(LMKD_CTRL_PACKET packet) {
-    struct lmk_procremove params;
-
-    if (use_inkernel_interface) {
-        return;
-    }
-
-    lmkd_pack_get_procremove(packet, &params);
-    /*
-     * WARNING: After pid_remove() procp is freed and can't be used!
-     * Therefore placed at the end of the function.
-     */
-    pid_remove(params.pid);
-}
-
-static void cmd_procpurge() {
-    int i;
-    struct proc *procp;
-    struct proc *next;
-
-    if (use_inkernel_interface) {
-        return;
-    }
-
-    for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
-        procadjslot_list[i].next = &procadjslot_list[i];
-        procadjslot_list[i].prev = &procadjslot_list[i];
-    }
-
-    for (i = 0; i < PIDHASH_SZ; i++) {
-        procp = pidhash[i];
-        while (procp) {
-            next = procp->pidhash_next;
-            free(procp);
-            procp = next;
-        }
-    }
-    memset(&pidhash[0], 0, sizeof(pidhash));
-}
-
-static void inc_killcnt(int oomadj) {
-    int slot = ADJTOSLOT(oomadj);
-    uint8_t idx = killcnt_idx[slot];
-
-    if (idx == KILLCNT_INVALID_IDX) {
-        /* index is not assigned for this oomadj */
-        if (killcnt_free_idx < MAX_DISTINCT_OOM_ADJ) {
-            killcnt_idx[slot] = killcnt_free_idx;
-            killcnt[killcnt_free_idx] = 1;
-            killcnt_free_idx++;
-        } else {
-            ALOGW("Number of distinct oomadj levels exceeds %d",
-                MAX_DISTINCT_OOM_ADJ);
-        }
-    } else {
-        /*
-         * wraparound is highly unlikely and is detectable using total
-         * counter because it has to be equal to the sum of all counters
-         */
-        killcnt[idx]++;
-    }
-    /* increment total kill counter */
-    killcnt_total++;
-}
-
-static int get_killcnt(int min_oomadj, int max_oomadj) {
-    int slot;
-    int count = 0;
-
-    if (min_oomadj > max_oomadj)
-        return 0;
-
-    /* special case to get total kill count */
-    if (min_oomadj > OOM_SCORE_ADJ_MAX)
-        return killcnt_total;
-
-    while (min_oomadj <= max_oomadj &&
-           (slot = ADJTOSLOT(min_oomadj)) < ADJTOSLOT_COUNT) {
-        uint8_t idx = killcnt_idx[slot];
-        if (idx != KILLCNT_INVALID_IDX) {
-            count += killcnt[idx];
-        }
-        min_oomadj++;
-    }
-
-    return count;
-}
-
-static int cmd_getkillcnt(LMKD_CTRL_PACKET packet) {
-    struct lmk_getkillcnt params;
-
-    if (use_inkernel_interface) {
-        /* kernel driver does not expose this information */
-        return 0;
-    }
-
-    lmkd_pack_get_getkillcnt(packet, &params);
-
-    return get_killcnt(params.min_oomadj, params.max_oomadj);
-}
-
-static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
-    int i;
-    struct lmk_target target;
-    char minfree_str[PROPERTY_VALUE_MAX];
-    char *pstr = minfree_str;
-    char *pend = minfree_str + sizeof(minfree_str);
-    static struct timespec last_req_tm;
-    struct timespec curr_tm;
-
-    if (ntargets < 1 || ntargets > (int)ARRAY_SIZE(lowmem_adj))
-        return;
-
-    /*
-     * Ratelimit minfree updates to once per TARGET_UPDATE_MIN_INTERVAL_MS
-     * to prevent DoS attacks
-     */
-    if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
-        ALOGE("Failed to get current time");
-        return;
-    }
-
-    if (get_time_diff_ms(&last_req_tm, &curr_tm) <
-        TARGET_UPDATE_MIN_INTERVAL_MS) {
-        ALOGE("Ignoring frequent updated to lmkd limits");
-        return;
-    }
-
-    last_req_tm = curr_tm;
-
-    for (i = 0; i < ntargets; i++) {
-        lmkd_pack_get_target(packet, i, &target);
-        lowmem_minfree[i] = target.minfree;
-        lowmem_adj[i] = target.oom_adj_score;
-
-        pstr += snprintf(pstr, pend - pstr, "%d:%d,", target.minfree,
-            target.oom_adj_score);
-        if (pstr >= pend) {
-            /* if no more space in the buffer then terminate the loop */
-            pstr = pend;
-            break;
-        }
-    }
-
-    lowmem_targets_size = ntargets;
-
-    /* Override the last extra comma */
-    pstr[-1] = '\0';
-    property_set("sys.lmk.minfree_levels", minfree_str);
-
-    if (has_inkernel_module) {
-        char minfreestr[128];
-        char killpriostr[128];
-
-        minfreestr[0] = '\0';
-        killpriostr[0] = '\0';
-
-        for (i = 0; i < lowmem_targets_size; i++) {
-            char val[40];
-
-            if (i) {
-                strlcat(minfreestr, ",", sizeof(minfreestr));
-                strlcat(killpriostr, ",", sizeof(killpriostr));
-            }
-
-            snprintf(val, sizeof(val), "%d", use_inkernel_interface ? lowmem_minfree[i] : 0);
-            strlcat(minfreestr, val, sizeof(minfreestr));
-            snprintf(val, sizeof(val), "%d", use_inkernel_interface ? lowmem_adj[i] : 0);
-            strlcat(killpriostr, val, sizeof(killpriostr));
-        }
-
-        writefilestring(INKERNEL_MINFREE_PATH, minfreestr, true);
-        writefilestring(INKERNEL_ADJ_PATH, killpriostr, true);
-    }
-}
-
-static void ctrl_data_close(int dsock_idx) {
-    struct epoll_event epev;
-
-    ALOGI("closing lmkd data connection");
-    if (epoll_ctl(epollfd, EPOLL_CTL_DEL, data_sock[dsock_idx].sock, &epev) == -1) {
-        // Log a warning and keep going
-        ALOGW("epoll_ctl for data connection socket failed; errno=%d", errno);
-    }
-    maxevents--;
-
-    close(data_sock[dsock_idx].sock);
-    data_sock[dsock_idx].sock = -1;
-}
-
-static int ctrl_data_read(int dsock_idx, char *buf, size_t bufsz) {
-    int ret = 0;
-
-    ret = TEMP_FAILURE_RETRY(read(data_sock[dsock_idx].sock, buf, bufsz));
-
-    if (ret == -1) {
-        ALOGE("control data socket read failed; errno=%d", errno);
-    } else if (ret == 0) {
-        ALOGE("Got EOF on control data socket");
-        ret = -1;
-    }
-
-    return ret;
-}
-
-static int ctrl_data_write(int dsock_idx, char *buf, size_t bufsz) {
-    int ret = 0;
-
-    ret = TEMP_FAILURE_RETRY(write(data_sock[dsock_idx].sock, buf, bufsz));
-
-    if (ret == -1) {
-        ALOGE("control data socket write failed; errno=%d", errno);
-    } else if (ret == 0) {
-        ALOGE("Got EOF on control data socket");
-        ret = -1;
-    }
-
-    return ret;
-}
-
-static void ctrl_command_handler(int dsock_idx) {
-    LMKD_CTRL_PACKET packet;
-    int len;
-    enum lmk_cmd cmd;
-    int nargs;
-    int targets;
-    int kill_cnt;
-
-    len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE);
-    if (len <= 0)
-        return;
-
-    if (len < (int)sizeof(int)) {
-        ALOGE("Wrong control socket read length len=%d", len);
-        return;
-    }
-
-    cmd = lmkd_pack_get_cmd(packet);
-    nargs = len / sizeof(int) - 1;
-    if (nargs < 0)
-        goto wronglen;
-
-    switch(cmd) {
-    case LMK_TARGET:
-        targets = nargs / 2;
-        if (nargs & 0x1 || targets > (int)ARRAY_SIZE(lowmem_adj))
-            goto wronglen;
-        cmd_target(targets, packet);
-        break;
-    case LMK_PROCPRIO:
-        if (nargs != 3)
-            goto wronglen;
-        cmd_procprio(packet);
-        break;
-    case LMK_PROCREMOVE:
-        if (nargs != 1)
-            goto wronglen;
-        cmd_procremove(packet);
-        break;
-    case LMK_PROCPURGE:
-        if (nargs != 0)
-            goto wronglen;
-        cmd_procpurge();
-        break;
-    case LMK_GETKILLCNT:
-        if (nargs != 2)
-            goto wronglen;
-        kill_cnt = cmd_getkillcnt(packet);
-        len = lmkd_pack_set_getkillcnt_repl(packet, kill_cnt);
-        if (ctrl_data_write(dsock_idx, (char *)packet, len) != len)
-            return;
-        break;
-    default:
-        ALOGE("Received unknown command code %d", cmd);
-        return;
-    }
-
-    return;
-
-wronglen:
-    ALOGE("Wrong control socket read length cmd=%d len=%d", cmd, len);
-}
-
-static void ctrl_data_handler(int data, uint32_t events) {
-    if (events & EPOLLIN) {
-        ctrl_command_handler(data);
-    }
-}
-
-static int get_free_dsock() {
-    for (int i = 0; i < MAX_DATA_CONN; i++) {
-        if (data_sock[i].sock < 0) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-static void ctrl_connect_handler(int data __unused, uint32_t events __unused) {
-    struct epoll_event epev;
-    int free_dscock_idx = get_free_dsock();
-
-    if (free_dscock_idx < 0) {
-        /*
-         * Number of data connections exceeded max supported. This should not
-         * happen but if it does we drop all existing connections and accept
-         * the new one. This prevents inactive connections from monopolizing
-         * data socket and if we drop ActivityManager connection it will
-         * immediately reconnect.
-         */
-        for (int i = 0; i < MAX_DATA_CONN; i++) {
-            ctrl_data_close(i);
-        }
-        free_dscock_idx = 0;
-    }
-
-    data_sock[free_dscock_idx].sock = accept(ctrl_sock.sock, NULL, NULL);
-    if (data_sock[free_dscock_idx].sock < 0) {
-        ALOGE("lmkd control socket accept failed; errno=%d", errno);
-        return;
-    }
-
-    ALOGI("lmkd data connection established");
-    /* use data to store data connection idx */
-    data_sock[free_dscock_idx].handler_info.data = free_dscock_idx;
-    data_sock[free_dscock_idx].handler_info.handler = ctrl_data_handler;
-    epev.events = EPOLLIN;
-    epev.data.ptr = (void *)&(data_sock[free_dscock_idx].handler_info);
-    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, data_sock[free_dscock_idx].sock, &epev) == -1) {
-        ALOGE("epoll_ctl for data connection socket failed; errno=%d", errno);
-        ctrl_data_close(free_dscock_idx);
-        return;
-    }
-    maxevents++;
-}
-
-#ifdef LMKD_LOG_STATS
-static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) {
-    char key[LINE_MAX + 1];
-    int64_t value;
-
-    sscanf(line, "%" STRINGIFY(LINE_MAX) "s  %" SCNd64 "", key, &value);
-
-    if (strcmp(key, "total_") < 0) {
-        return;
-    }
-
-    if (!strcmp(key, "total_pgfault"))
-        mem_st->pgfault = value;
-    else if (!strcmp(key, "total_pgmajfault"))
-        mem_st->pgmajfault = value;
-    else if (!strcmp(key, "total_rss"))
-        mem_st->rss_in_bytes = value;
-    else if (!strcmp(key, "total_cache"))
-        mem_st->cache_in_bytes = value;
-    else if (!strcmp(key, "total_swap"))
-        mem_st->swap_in_bytes = value;
-}
-
-static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
-    FILE *fp;
-    char buf[PATH_MAX];
-
-    snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
-
-    fp = fopen(buf, "r");
-
-    if (fp == NULL) {
-        ALOGE("%s open failed: %s", buf, strerror(errno));
-        return -1;
-    }
-
-    while (fgets(buf, PAGE_SIZE, fp) != NULL) {
-        memory_stat_parse_line(buf, mem_st);
-    }
-    fclose(fp);
-
-    return 0;
-}
-
-static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) {
-    char path[PATH_MAX];
-    char buffer[PROC_STAT_BUFFER_SIZE];
-    int fd, ret;
-
-    snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid);
-    if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
-        ALOGE("%s open failed: %s", path, strerror(errno));
-        return -1;
-    }
-
-    ret = read(fd, buffer, sizeof(buffer));
-    if (ret < 0) {
-        ALOGE("%s read failed: %s", path, strerror(errno));
-        close(fd);
-        return -1;
-    }
-    close(fd);
-
-    // field 10 is pgfault
-    // field 12 is pgmajfault
-    // field 22 is starttime
-    // field 24 is rss_in_pages
-    int64_t pgfault = 0, pgmajfault = 0, starttime = 0, rss_in_pages = 0;
-    if (sscanf(buffer,
-               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d "
-               "%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d "
-               "%" SCNd64 " %*d %" SCNd64 "",
-               &pgfault, &pgmajfault, &starttime, &rss_in_pages) != 4) {
-        return -1;
-    }
-    mem_st->pgfault = pgfault;
-    mem_st->pgmajfault = pgmajfault;
-    mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE);
-    mem_st->process_start_time_ns = starttime * (NS_PER_SEC / sysconf(_SC_CLK_TCK));
-    return 0;
-}
-#endif
-
-/* /prop/zoneinfo parsing routines */
-static int64_t zoneinfo_parse_protection(char *cp) {
-    int64_t max = 0;
-    long long zoneval;
-    char *save_ptr;
-
-    for (cp = strtok_r(cp, "(), ", &save_ptr); cp;
-         cp = strtok_r(NULL, "), ", &save_ptr)) {
-        zoneval = strtoll(cp, &cp, 0);
-        if (zoneval > max) {
-            max = (zoneval > INT64_MAX) ? INT64_MAX : zoneval;
-        }
-    }
-
-    return max;
-}
-
-static bool zoneinfo_parse_line(char *line, union zoneinfo *zi) {
-    char *cp = line;
-    char *ap;
-    char *save_ptr;
-    int64_t val;
-    int field_idx;
-
-    cp = strtok_r(line, " ", &save_ptr);
-    if (!cp) {
-        return true;
-    }
-
-    if (!strcmp(cp, "protection:")) {
-        ap = strtok_r(NULL, ")", &save_ptr);
-    } else {
-        ap = strtok_r(NULL, " ", &save_ptr);
-    }
-
-    if (!ap) {
-        return true;
-    }
-
-    switch (match_field(cp, ap, zoneinfo_field_names,
-                        ZI_FIELD_COUNT, &val, &field_idx)) {
-    case (PARSE_SUCCESS):
-        zi->arr[field_idx] += val;
-        break;
-    case (NO_MATCH):
-        if (!strcmp(cp, "protection:")) {
-            zi->field.totalreserve_pages +=
-                zoneinfo_parse_protection(ap);
-        }
-        break;
-    case (PARSE_FAIL):
-    default:
-        return false;
-    }
-    return true;
-}
-
-static int zoneinfo_parse(union zoneinfo *zi) {
-    static struct reread_data file_data = {
-        .filename = ZONEINFO_PATH,
-        .fd = -1,
-    };
-    char buf[PAGE_SIZE];
-    char *save_ptr;
-    char *line;
-
-    memset(zi, 0, sizeof(union zoneinfo));
-
-    if (reread_file(&file_data, buf, sizeof(buf)) < 0) {
-        return -1;
-    }
-
-    for (line = strtok_r(buf, "\n", &save_ptr); line;
-         line = strtok_r(NULL, "\n", &save_ptr)) {
-        if (!zoneinfo_parse_line(line, zi)) {
-            ALOGE("%s parse error", file_data.filename);
-            return -1;
-        }
-    }
-    zi->field.totalreserve_pages += zi->field.high;
-
-    return 0;
-}
-
-/* /prop/meminfo parsing routines */
-static bool meminfo_parse_line(char *line, union meminfo *mi) {
-    char *cp = line;
-    char *ap;
-    char *save_ptr;
-    int64_t val;
-    int field_idx;
-    enum field_match_result match_res;
-
-    cp = strtok_r(line, " ", &save_ptr);
-    if (!cp) {
-        return false;
-    }
-
-    ap = strtok_r(NULL, " ", &save_ptr);
-    if (!ap) {
-        return false;
-    }
-
-    match_res = match_field(cp, ap, meminfo_field_names, MI_FIELD_COUNT,
-        &val, &field_idx);
-    if (match_res == PARSE_SUCCESS) {
-        mi->arr[field_idx] = val / page_k;
-    }
-    return (match_res != PARSE_FAIL);
-}
-
-static int meminfo_parse(union meminfo *mi) {
-    static struct reread_data file_data = {
-        .filename = MEMINFO_PATH,
-        .fd = -1,
-    };
-    char buf[PAGE_SIZE];
-    char *save_ptr;
-    char *line;
-
-    memset(mi, 0, sizeof(union meminfo));
-
-    if (reread_file(&file_data, buf, sizeof(buf)) < 0) {
-        return -1;
-    }
-
-    for (line = strtok_r(buf, "\n", &save_ptr); line;
-         line = strtok_r(NULL, "\n", &save_ptr)) {
-        if (!meminfo_parse_line(line, mi)) {
-            ALOGE("%s parse error", file_data.filename);
-            return -1;
-        }
-    }
-    mi->field.nr_file_pages = mi->field.cached + mi->field.swap_cached +
-        mi->field.buffers;
-
-    return 0;
-}
-
-static void meminfo_log(union meminfo *mi) {
-    for (int field_idx = 0; field_idx < MI_FIELD_COUNT; field_idx++) {
-        android_log_write_int32(ctx, (int32_t)min(mi->arr[field_idx] * page_k, INT32_MAX));
-    }
-
-    android_log_write_list(ctx, LOG_ID_EVENTS);
-    android_log_reset(ctx);
-}
-
-static int proc_get_size(int pid) {
-    char path[PATH_MAX];
-    char line[LINE_MAX];
-    int fd;
-    int rss = 0;
-    int total;
-    ssize_t ret;
-
-    /* gid containing AID_READPROC required */
-    snprintf(path, PATH_MAX, "/proc/%d/statm", pid);
-    fd = open(path, O_RDONLY | O_CLOEXEC);
-    if (fd == -1)
-        return -1;
-
-    ret = read_all(fd, line, sizeof(line) - 1);
-    if (ret < 0) {
-        close(fd);
-        return -1;
-    }
-
-    sscanf(line, "%d %d ", &total, &rss);
-    close(fd);
-    return rss;
-}
-
-static char *proc_get_name(int pid) {
-    char path[PATH_MAX];
-    static char line[LINE_MAX];
-    int fd;
-    char *cp;
-    ssize_t ret;
-
-    /* gid containing AID_READPROC required */
-    snprintf(path, PATH_MAX, "/proc/%d/cmdline", pid);
-    fd = open(path, O_RDONLY | O_CLOEXEC);
-    if (fd == -1)
-        return NULL;
-    ret = read_all(fd, line, sizeof(line) - 1);
-    close(fd);
-    if (ret < 0) {
-        return NULL;
-    }
-
-    cp = strchr(line, ' ');
-    if (cp)
-        *cp = '\0';
-
-    return line;
-}
-
-static struct proc *proc_adj_lru(int oomadj) {
-    return (struct proc *)adjslot_tail(&procadjslot_list[ADJTOSLOT(oomadj)]);
-}
-
-static struct proc *proc_get_heaviest(int oomadj) {
-    struct adjslot_list *head = &procadjslot_list[ADJTOSLOT(oomadj)];
-    struct adjslot_list *curr = head->next;
-    struct proc *maxprocp = NULL;
-    int maxsize = 0;
-    while (curr != head) {
-        int pid = ((struct proc *)curr)->pid;
-        int tasksize = proc_get_size(pid);
-        if (tasksize <= 0) {
-            struct adjslot_list *next = curr->next;
-            pid_remove(pid);
-            curr = next;
-        } else {
-            if (tasksize > maxsize) {
-                maxsize = tasksize;
-                maxprocp = (struct proc *)curr;
-            }
-            curr = curr->next;
-        }
-    }
-    return maxprocp;
-}
-
-static void set_process_group_and_prio(int pid, SchedPolicy sp, int prio) {
-    DIR* d;
-    char proc_path[PATH_MAX];
-    struct dirent* de;
-
-    snprintf(proc_path, sizeof(proc_path), "/proc/%d/task", pid);
-    if (!(d = opendir(proc_path))) {
-        ALOGW("Failed to open %s; errno=%d: process pid(%d) might have died", proc_path, errno,
-              pid);
-        return;
-    }
-
-    while ((de = readdir(d))) {
-        int t_pid;
-
-        if (de->d_name[0] == '.') continue;
-        t_pid = atoi(de->d_name);
-
-        if (!t_pid) {
-            ALOGW("Failed to get t_pid for '%s' of pid(%d)", de->d_name, pid);
-            continue;
-        }
-
-        if (setpriority(PRIO_PROCESS, t_pid, prio) && errno != ESRCH) {
-            ALOGW("Unable to raise priority of killing t_pid (%d): errno=%d", t_pid, errno);
-        }
-
-        if (set_cpuset_policy(t_pid, sp)) {
-            ALOGW("Failed to set_cpuset_policy on pid(%d) t_pid(%d) to %d", pid, t_pid, (int)sp);
-            continue;
-        }
-    }
-    closedir(d);
-}
-
-static int last_killed_pid = -1;
-
-/* Kill one process specified by procp.  Returns the size of the process killed */
-static int kill_one_process(struct proc* procp, int min_oom_score) {
-    int pid = procp->pid;
-    uid_t uid = procp->uid;
-    int tgid;
-    char *taskname;
-    int tasksize;
-    int r;
-    int result = -1;
-
-#ifdef LMKD_LOG_STATS
-    struct memory_stat mem_st = {};
-    int memory_stat_parse_result = -1;
-#else
-    /* To prevent unused parameter warning */
-    (void)(min_oom_score);
-#endif
-
-    tgid = proc_get_tgid(pid);
-    if (tgid >= 0 && tgid != pid) {
-        ALOGE("Possible pid reuse detected (pid %d, tgid %d)!", pid, tgid);
-        goto out;
-    }
-
-    taskname = proc_get_name(pid);
-    if (!taskname) {
-        goto out;
-    }
-
-    tasksize = proc_get_size(pid);
-    if (tasksize <= 0) {
-        goto out;
-    }
-
-#ifdef LMKD_LOG_STATS
-    if (enable_stats_log) {
-        if (per_app_memcg) {
-            memory_stat_parse_result = memory_stat_from_cgroup(&mem_st, pid, uid);
-        } else {
-            memory_stat_parse_result = memory_stat_from_procfs(&mem_st, pid);
-        }
-    }
-#endif
-
-    TRACE_KILL_START(pid);
-
-    /* CAP_KILL required */
-    r = kill(pid, SIGKILL);
-
-    set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
-
-    inc_killcnt(procp->oomadj);
-    ALOGE("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", taskname, pid, uid, procp->oomadj,
-          tasksize * page_k);
-
-    TRACE_KILL_END();
-
-    last_killed_pid = pid;
-
-    if (r) {
-        ALOGE("kill(%d): errno=%d", pid, errno);
-        goto out;
-    } else {
-#ifdef LMKD_LOG_STATS
-        if (memory_stat_parse_result == 0) {
-            stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
-                    procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
-                    mem_st.cache_in_bytes, mem_st.swap_in_bytes, mem_st.process_start_time_ns,
-                    min_oom_score);
-        } else if (enable_stats_log) {
-            stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, procp->oomadj,
-                                          -1, -1, tasksize * BYTES_IN_KILOBYTE, -1, -1, -1,
-                                          min_oom_score);
-        }
-#endif
-        result = tasksize;
-    }
-
-out:
-    /*
-     * WARNING: After pid_remove() procp is freed and can't be used!
-     * Therefore placed at the end of the function.
-     */
-    pid_remove(pid);
-    return result;
-}
-
-/*
- * Find one process to kill at or above the given oom_adj level.
- * Returns size of the killed process.
- */
-static int find_and_kill_process(int min_score_adj) {
-    int i;
-    int killed_size = 0;
-
-#ifdef LMKD_LOG_STATS
-    bool lmk_state_change_start = false;
-#endif
-
-    for (i = OOM_SCORE_ADJ_MAX; i >= min_score_adj; i--) {
-        struct proc *procp;
-
-        while (true) {
-            procp = kill_heaviest_task ?
-                proc_get_heaviest(i) : proc_adj_lru(i);
-
-            if (!procp)
-                break;
-
-            killed_size = kill_one_process(procp, min_score_adj);
-            if (killed_size >= 0) {
-#ifdef LMKD_LOG_STATS
-                if (enable_stats_log && !lmk_state_change_start) {
-                    lmk_state_change_start = true;
-                    stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED,
-                                                  LMK_STATE_CHANGE_START);
-                }
-#endif
-                break;
-            }
-        }
-        if (killed_size) {
-            break;
-        }
-    }
-
-#ifdef LMKD_LOG_STATS
-    if (enable_stats_log && lmk_state_change_start) {
-        stats_write_lmk_state_changed(log_ctx, LMK_STATE_CHANGED, LMK_STATE_CHANGE_STOP);
-    }
-#endif
-
-    return killed_size;
-}
-
-static int64_t get_memory_usage(struct reread_data *file_data) {
-    int ret;
-    int64_t mem_usage;
-    char buf[32];
-
-    if (reread_file(file_data, buf, sizeof(buf)) < 0) {
-        return -1;
-    }
-
-    if (!parse_int64(buf, &mem_usage)) {
-        ALOGE("%s parse error", file_data->filename);
-        return -1;
-    }
-    if (mem_usage == 0) {
-        ALOGE("No memory!");
-        return -1;
-    }
-    return mem_usage;
-}
-
-void record_low_pressure_levels(union meminfo *mi) {
-    if (low_pressure_mem.min_nr_free_pages == -1 ||
-        low_pressure_mem.min_nr_free_pages > mi->field.nr_free_pages) {
-        if (debug_process_killing) {
-            ALOGI("Low pressure min memory update from %" PRId64 " to %" PRId64,
-                low_pressure_mem.min_nr_free_pages, mi->field.nr_free_pages);
-        }
-        low_pressure_mem.min_nr_free_pages = mi->field.nr_free_pages;
-    }
-    /*
-     * Free memory at low vmpressure events occasionally gets spikes,
-     * possibly a stale low vmpressure event with memory already
-     * freed up (no memory pressure should have been reported).
-     * Ignore large jumps in max_nr_free_pages that would mess up our stats.
-     */
-    if (low_pressure_mem.max_nr_free_pages == -1 ||
-        (low_pressure_mem.max_nr_free_pages < mi->field.nr_free_pages &&
-         mi->field.nr_free_pages - low_pressure_mem.max_nr_free_pages <
-         low_pressure_mem.max_nr_free_pages * 0.1)) {
-        if (debug_process_killing) {
-            ALOGI("Low pressure max memory update from %" PRId64 " to %" PRId64,
-                low_pressure_mem.max_nr_free_pages, mi->field.nr_free_pages);
-        }
-        low_pressure_mem.max_nr_free_pages = mi->field.nr_free_pages;
-    }
-}
-
-enum vmpressure_level upgrade_level(enum vmpressure_level level) {
-    return (enum vmpressure_level)((level < VMPRESS_LEVEL_CRITICAL) ?
-        level + 1 : level);
-}
-
-enum vmpressure_level downgrade_level(enum vmpressure_level level) {
-    return (enum vmpressure_level)((level > VMPRESS_LEVEL_LOW) ?
-        level - 1 : level);
-}
-
-static bool is_kill_pending(void) {
-    char buf[24];
-
-    if (last_killed_pid < 0) {
-        return false;
-    }
-
-    snprintf(buf, sizeof(buf), "/proc/%d/", last_killed_pid);
-    if (access(buf, F_OK) == 0) {
-        return true;
-    }
-
-    // reset last killed PID because there's nothing pending
-    last_killed_pid = -1;
-    return false;
-}
-
-static void mp_event_common(int data, uint32_t events __unused) {
-    int ret;
-    unsigned long long evcount;
-    int64_t mem_usage, memsw_usage;
-    int64_t mem_pressure;
-    enum vmpressure_level lvl;
-    union meminfo mi;
-    union zoneinfo zi;
-    struct timespec curr_tm;
-    static struct timespec last_kill_tm;
-    static unsigned long kill_skip_count = 0;
-    enum vmpressure_level level = (enum vmpressure_level)data;
-    long other_free = 0, other_file = 0;
-    int min_score_adj;
-    int minfree = 0;
-    static struct reread_data mem_usage_file_data = {
-        .filename = MEMCG_MEMORY_USAGE,
-        .fd = -1,
-    };
-    static struct reread_data memsw_usage_file_data = {
-        .filename = MEMCG_MEMORYSW_USAGE,
-        .fd = -1,
-    };
-
-    if (debug_process_killing) {
-        ALOGI("%s memory pressure event is triggered", level_name[level]);
-    }
-
-    if (!use_psi_monitors) {
-        /*
-         * Check all event counters from low to critical
-         * and upgrade to the highest priority one. By reading
-         * eventfd we also reset the event counters.
-         */
-        for (lvl = VMPRESS_LEVEL_LOW; lvl < VMPRESS_LEVEL_COUNT; lvl++) {
-            if (mpevfd[lvl] != -1 &&
-                TEMP_FAILURE_RETRY(read(mpevfd[lvl],
-                                   &evcount, sizeof(evcount))) > 0 &&
-                evcount > 0 && lvl > level) {
-                level = lvl;
-            }
-        }
-    }
-
-    if (clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm) != 0) {
-        ALOGE("Failed to get current time");
-        return;
-    }
-
-    if (kill_timeout_ms) {
-        // If we're within the timeout, see if there's pending reclaim work
-        // from the last killed process. If there is (as evidenced by
-        // /proc/<pid> continuing to exist), skip killing for now.
-        if ((get_time_diff_ms(&last_kill_tm, &curr_tm) < kill_timeout_ms) &&
-            (low_ram_device || is_kill_pending())) {
-            kill_skip_count++;
-            return;
-        }
-    }
-
-    if (kill_skip_count > 0) {
-        ALOGI("%lu memory pressure events were skipped after a kill!",
-              kill_skip_count);
-        kill_skip_count = 0;
-    }
-
-    if (meminfo_parse(&mi) < 0 || zoneinfo_parse(&zi) < 0) {
-        ALOGE("Failed to get free memory!");
-        return;
-    }
-
-    if (use_minfree_levels) {
-        int i;
-
-        other_free = mi.field.nr_free_pages - zi.field.totalreserve_pages;
-        if (mi.field.nr_file_pages > (mi.field.shmem + mi.field.unevictable + mi.field.swap_cached)) {
-            other_file = (mi.field.nr_file_pages - mi.field.shmem -
-                          mi.field.unevictable - mi.field.swap_cached);
-        } else {
-            other_file = 0;
-        }
-
-        min_score_adj = OOM_SCORE_ADJ_MAX + 1;
-        for (i = 0; i < lowmem_targets_size; i++) {
-            minfree = lowmem_minfree[i];
-            if (other_free < minfree && other_file < minfree) {
-                min_score_adj = lowmem_adj[i];
-                break;
-            }
-        }
-
-        if (min_score_adj == OOM_SCORE_ADJ_MAX + 1) {
-            if (debug_process_killing) {
-                ALOGI("Ignore %s memory pressure event "
-                      "(free memory=%ldkB, cache=%ldkB, limit=%ldkB)",
-                      level_name[level], other_free * page_k, other_file * page_k,
-                      (long)lowmem_minfree[lowmem_targets_size - 1] * page_k);
-            }
-            return;
-        }
-
-        goto do_kill;
-    }
-
-    if (level == VMPRESS_LEVEL_LOW) {
-        record_low_pressure_levels(&mi);
-    }
-
-    if (level_oomadj[level] > OOM_SCORE_ADJ_MAX) {
-        /* Do not monitor this pressure level */
-        return;
-    }
-
-    if ((mem_usage = get_memory_usage(&mem_usage_file_data)) < 0) {
-        goto do_kill;
-    }
-    if ((memsw_usage = get_memory_usage(&memsw_usage_file_data)) < 0) {
-        goto do_kill;
-    }
-
-    // Calculate percent for swappinness.
-    mem_pressure = (mem_usage * 100) / memsw_usage;
-
-    if (enable_pressure_upgrade && level != VMPRESS_LEVEL_CRITICAL) {
-        // We are swapping too much.
-        if (mem_pressure < upgrade_pressure) {
-            level = upgrade_level(level);
-            if (debug_process_killing) {
-                ALOGI("Event upgraded to %s", level_name[level]);
-            }
-        }
-    }
-
-    // If we still have enough swap space available, check if we want to
-    // ignore/downgrade pressure events.
-    if (mi.field.free_swap >=
-        mi.field.total_swap * swap_free_low_percentage / 100) {
-        // If the pressure is larger than downgrade_pressure lmk will not
-        // kill any process, since enough memory is available.
-        if (mem_pressure > downgrade_pressure) {
-            if (debug_process_killing) {
-                ALOGI("Ignore %s memory pressure", level_name[level]);
-            }
-            return;
-        } else if (level == VMPRESS_LEVEL_CRITICAL && mem_pressure > upgrade_pressure) {
-            if (debug_process_killing) {
-                ALOGI("Downgrade critical memory pressure");
-            }
-            // Downgrade event, since enough memory available.
-            level = downgrade_level(level);
-        }
-    }
-
-do_kill:
-    if (low_ram_device) {
-        /* For Go devices kill only one task */
-        if (find_and_kill_process(level_oomadj[level]) == 0) {
-            if (debug_process_killing) {
-                ALOGI("Nothing to kill");
-            }
-        } else {
-            meminfo_log(&mi);
-        }
-    } else {
-        int pages_freed;
-        static struct timespec last_report_tm;
-        static unsigned long report_skip_count = 0;
-
-        if (!use_minfree_levels) {
-            /* Free up enough memory to downgrate the memory pressure to low level */
-            if (mi.field.nr_free_pages >= low_pressure_mem.max_nr_free_pages) {
-                if (debug_process_killing) {
-                    ALOGI("Ignoring pressure since more memory is "
-                        "available (%" PRId64 ") than watermark (%" PRId64 ")",
-                        mi.field.nr_free_pages, low_pressure_mem.max_nr_free_pages);
-                }
-                return;
-            }
-            min_score_adj = level_oomadj[level];
-        }
-
-        pages_freed = find_and_kill_process(min_score_adj);
-
-        if (pages_freed == 0) {
-            /* Rate limit kill reports when nothing was reclaimed */
-            if (get_time_diff_ms(&last_report_tm, &curr_tm) < FAIL_REPORT_RLIMIT_MS) {
-                report_skip_count++;
-                return;
-            }
-        } else {
-            /* If we killed anything, update the last killed timestamp. */
-            last_kill_tm = curr_tm;
-        }
-
-        /* Log meminfo whenever we kill or when report rate limit allows */
-        meminfo_log(&mi);
-
-        if (use_minfree_levels) {
-            ALOGI("Reclaimed %ldkB, cache(%ldkB) and "
-                "free(%" PRId64 "kB)-reserved(%" PRId64 "kB) below min(%ldkB) for oom_adj %d",
-                pages_freed * page_k,
-                other_file * page_k, mi.field.nr_free_pages * page_k,
-                zi.field.totalreserve_pages * page_k,
-                minfree * page_k, min_score_adj);
-        } else {
-            ALOGI("Reclaimed %ldkB at oom_adj %d",
-                pages_freed * page_k, min_score_adj);
-        }
-
-        if (report_skip_count > 0) {
-            ALOGI("Suppressed %lu failed kill reports", report_skip_count);
-            report_skip_count = 0;
-        }
-
-        last_report_tm = curr_tm;
-    }
-}
-
-static bool init_mp_psi(enum vmpressure_level level) {
-    int fd = init_psi_monitor(psi_thresholds[level].stall_type,
-        psi_thresholds[level].threshold_ms * US_PER_MS,
-        PSI_WINDOW_SIZE_MS * US_PER_MS);
-
-    if (fd < 0) {
-        return false;
-    }
-
-    vmpressure_hinfo[level].handler = mp_event_common;
-    vmpressure_hinfo[level].data = level;
-    if (register_psi_monitor(epollfd, fd, &vmpressure_hinfo[level]) < 0) {
-        destroy_psi_monitor(fd);
-        return false;
-    }
-    maxevents++;
-    mpevfd[level] = fd;
-
-    return true;
-}
-
-static void destroy_mp_psi(enum vmpressure_level level) {
-    int fd = mpevfd[level];
-
-    if (unregister_psi_monitor(epollfd, fd) < 0) {
-        ALOGE("Failed to unregister psi monitor for %s memory pressure; errno=%d",
-            level_name[level], errno);
-    }
-    destroy_psi_monitor(fd);
-    mpevfd[level] = -1;
-}
-
-static bool init_psi_monitors() {
-    if (!init_mp_psi(VMPRESS_LEVEL_LOW)) {
-        return false;
-    }
-    if (!init_mp_psi(VMPRESS_LEVEL_MEDIUM)) {
-        destroy_mp_psi(VMPRESS_LEVEL_LOW);
-        return false;
-    }
-    if (!init_mp_psi(VMPRESS_LEVEL_CRITICAL)) {
-        destroy_mp_psi(VMPRESS_LEVEL_MEDIUM);
-        destroy_mp_psi(VMPRESS_LEVEL_LOW);
-        return false;
-    }
-    return true;
-}
-
-static bool init_mp_common(enum vmpressure_level level) {
-    int mpfd;
-    int evfd;
-    int evctlfd;
-    char buf[256];
-    struct epoll_event epev;
-    int ret;
-    int level_idx = (int)level;
-    const char *levelstr = level_name[level_idx];
-
-    /* gid containing AID_SYSTEM required */
-    mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY | O_CLOEXEC);
-    if (mpfd < 0) {
-        ALOGI("No kernel memory.pressure_level support (errno=%d)", errno);
-        goto err_open_mpfd;
-    }
-
-    evctlfd = open(MEMCG_SYSFS_PATH "cgroup.event_control", O_WRONLY | O_CLOEXEC);
-    if (evctlfd < 0) {
-        ALOGI("No kernel memory cgroup event control (errno=%d)", errno);
-        goto err_open_evctlfd;
-    }
-
-    evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
-    if (evfd < 0) {
-        ALOGE("eventfd failed for level %s; errno=%d", levelstr, errno);
-        goto err_eventfd;
-    }
-
-    ret = snprintf(buf, sizeof(buf), "%d %d %s", evfd, mpfd, levelstr);
-    if (ret >= (ssize_t)sizeof(buf)) {
-        ALOGE("cgroup.event_control line overflow for level %s", levelstr);
-        goto err;
-    }
-
-    ret = TEMP_FAILURE_RETRY(write(evctlfd, buf, strlen(buf) + 1));
-    if (ret == -1) {
-        ALOGE("cgroup.event_control write failed for level %s; errno=%d",
-              levelstr, errno);
-        goto err;
-    }
-
-    epev.events = EPOLLIN;
-    /* use data to store event level */
-    vmpressure_hinfo[level_idx].data = level_idx;
-    vmpressure_hinfo[level_idx].handler = mp_event_common;
-    epev.data.ptr = (void *)&vmpressure_hinfo[level_idx];
-    ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, evfd, &epev);
-    if (ret == -1) {
-        ALOGE("epoll_ctl for level %s failed; errno=%d", levelstr, errno);
-        goto err;
-    }
-    maxevents++;
-    mpevfd[level] = evfd;
-    close(evctlfd);
-    return true;
-
-err:
-    close(evfd);
-err_eventfd:
-    close(evctlfd);
-err_open_evctlfd:
-    close(mpfd);
-err_open_mpfd:
-    return false;
-}
-
-static int init(void) {
-    struct epoll_event epev;
-    int i;
-    int ret;
-
-    page_k = sysconf(_SC_PAGESIZE);
-    if (page_k == -1)
-        page_k = PAGE_SIZE;
-    page_k /= 1024;
-
-    epollfd = epoll_create(MAX_EPOLL_EVENTS);
-    if (epollfd == -1) {
-        ALOGE("epoll_create failed (errno=%d)", errno);
-        return -1;
-    }
-
-    // mark data connections as not connected
-    for (int i = 0; i < MAX_DATA_CONN; i++) {
-        data_sock[i].sock = -1;
-    }
-
-    ctrl_sock.sock = android_get_control_socket("lmkd");
-    if (ctrl_sock.sock < 0) {
-        ALOGE("get lmkd control socket failed");
-        return -1;
-    }
-
-    ret = listen(ctrl_sock.sock, MAX_DATA_CONN);
-    if (ret < 0) {
-        ALOGE("lmkd control socket listen failed (errno=%d)", errno);
-        return -1;
-    }
-
-    epev.events = EPOLLIN;
-    ctrl_sock.handler_info.handler = ctrl_connect_handler;
-    epev.data.ptr = (void *)&(ctrl_sock.handler_info);
-    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ctrl_sock.sock, &epev) == -1) {
-        ALOGE("epoll_ctl for lmkd control socket failed (errno=%d)", errno);
-        return -1;
-    }
-    maxevents++;
-
-    has_inkernel_module = !access(INKERNEL_MINFREE_PATH, W_OK);
-    use_inkernel_interface = has_inkernel_module;
-
-    if (use_inkernel_interface) {
-        ALOGI("Using in-kernel low memory killer interface");
-    } else {
-        /* Try to use psi monitor first if kernel has it */
-        use_psi_monitors = property_get_bool("ro.lmk.use_psi", true) &&
-            init_psi_monitors();
-        /* Fall back to vmpressure */
-        if (!use_psi_monitors &&
-            (!init_mp_common(VMPRESS_LEVEL_LOW) ||
-            !init_mp_common(VMPRESS_LEVEL_MEDIUM) ||
-            !init_mp_common(VMPRESS_LEVEL_CRITICAL))) {
-            ALOGE("Kernel does not support memory pressure events or in-kernel low memory killer");
-            return -1;
-        }
-        if (use_psi_monitors) {
-            ALOGI("Using psi monitors for memory pressure detection");
-        } else {
-            ALOGI("Using vmpressure for memory pressure detection");
-        }
-    }
-
-    for (i = 0; i <= ADJTOSLOT(OOM_SCORE_ADJ_MAX); i++) {
-        procadjslot_list[i].next = &procadjslot_list[i];
-        procadjslot_list[i].prev = &procadjslot_list[i];
-    }
-
-    memset(killcnt_idx, KILLCNT_INVALID_IDX, sizeof(killcnt_idx));
-
-    return 0;
-}
-
-static void mainloop(void) {
-    struct event_handler_info* handler_info;
-    struct event_handler_info* poll_handler = NULL;
-    struct timespec last_report_tm, curr_tm;
-    struct epoll_event *evt;
-    long delay = -1;
-    int polling = 0;
-
-    while (1) {
-        struct epoll_event events[maxevents];
-        int nevents;
-        int i;
-
-        if (polling) {
-            /* Calculate next timeout */
-            clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
-            delay = get_time_diff_ms(&last_report_tm, &curr_tm);
-            delay = (delay < PSI_POLL_PERIOD_MS) ?
-                PSI_POLL_PERIOD_MS - delay : PSI_POLL_PERIOD_MS;
-
-            /* Wait for events until the next polling timeout */
-            nevents = epoll_wait(epollfd, events, maxevents, delay);
-
-            clock_gettime(CLOCK_MONOTONIC_COARSE, &curr_tm);
-            if (get_time_diff_ms(&last_report_tm, &curr_tm) >= PSI_POLL_PERIOD_MS) {
-                polling--;
-                poll_handler->handler(poll_handler->data, 0);
-                last_report_tm = curr_tm;
-            }
-        } else {
-            /* Wait for events with no timeout */
-            nevents = epoll_wait(epollfd, events, maxevents, -1);
-        }
-
-        if (nevents == -1) {
-            if (errno == EINTR)
-                continue;
-            ALOGE("epoll_wait failed (errno=%d)", errno);
-            continue;
-        }
-
-        /*
-         * First pass to see if any data socket connections were dropped.
-         * Dropped connection should be handled before any other events
-         * to deallocate data connection and correctly handle cases when
-         * connection gets dropped and reestablished in the same epoll cycle.
-         * In such cases it's essential to handle connection closures first.
-         */
-        for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
-            if ((evt->events & EPOLLHUP) && evt->data.ptr) {
-                ALOGI("lmkd data connection dropped");
-                handler_info = (struct event_handler_info*)evt->data.ptr;
-                ctrl_data_close(handler_info->data);
-            }
-        }
-
-        /* Second pass to handle all other events */
-        for (i = 0, evt = &events[0]; i < nevents; ++i, evt++) {
-            if (evt->events & EPOLLERR)
-                ALOGD("EPOLLERR on event #%d", i);
-            if (evt->events & EPOLLHUP) {
-                /* This case was handled in the first pass */
-                continue;
-            }
-            if (evt->data.ptr) {
-                handler_info = (struct event_handler_info*)evt->data.ptr;
-                handler_info->handler(handler_info->data, evt->events);
-
-                if (use_psi_monitors && handler_info->handler == mp_event_common) {
-                    /*
-                     * Poll for the duration of PSI_WINDOW_SIZE_MS after the
-                     * initial PSI event because psi events are rate-limited
-                     * at one per sec.
-                     */
-                    polling = PSI_POLL_COUNT;
-                    poll_handler = handler_info;
-                    clock_gettime(CLOCK_MONOTONIC_COARSE, &last_report_tm);
-                }
-            }
-        }
-    }
-}
-
-int main(int argc __unused, char **argv __unused) {
-    struct sched_param param = {
-            .sched_priority = 1,
-    };
-
-    /* By default disable low level vmpressure events */
-    level_oomadj[VMPRESS_LEVEL_LOW] =
-        property_get_int32("ro.lmk.low", OOM_SCORE_ADJ_MAX + 1);
-    level_oomadj[VMPRESS_LEVEL_MEDIUM] =
-        property_get_int32("ro.lmk.medium", 800);
-    level_oomadj[VMPRESS_LEVEL_CRITICAL] =
-        property_get_int32("ro.lmk.critical", 0);
-    debug_process_killing = property_get_bool("ro.lmk.debug", false);
-
-    /* By default disable upgrade/downgrade logic */
-    enable_pressure_upgrade =
-        property_get_bool("ro.lmk.critical_upgrade", false);
-    upgrade_pressure =
-        (int64_t)property_get_int32("ro.lmk.upgrade_pressure", 100);
-    downgrade_pressure =
-        (int64_t)property_get_int32("ro.lmk.downgrade_pressure", 100);
-    kill_heaviest_task =
-        property_get_bool("ro.lmk.kill_heaviest_task", false);
-    low_ram_device = property_get_bool("ro.config.low_ram", false);
-    kill_timeout_ms =
-        (unsigned long)property_get_int32("ro.lmk.kill_timeout_ms", 0);
-    use_minfree_levels =
-        property_get_bool("ro.lmk.use_minfree_levels", false);
-    per_app_memcg =
-        property_get_bool("ro.config.per_app_memcg", low_ram_device);
-    swap_free_low_percentage =
-        property_get_int32("ro.lmk.swap_free_low_percentage", 10);
-
-    ctx = create_android_logger(MEMINFO_LOG_TAG);
-
-#ifdef LMKD_LOG_STATS
-    statslog_init(&log_ctx, &enable_stats_log);
-#endif
-
-    if (!init()) {
-        if (!use_inkernel_interface) {
-            /*
-             * MCL_ONFAULT pins pages as they fault instead of loading
-             * everything immediately all at once. (Which would be bad,
-             * because as of this writing, we have a lot of mapped pages we
-             * never use.) Old kernels will see MCL_ONFAULT and fail with
-             * EINVAL; we ignore this failure.
-             *
-             * N.B. read the man page for mlockall. MCL_CURRENT | MCL_ONFAULT
-             * pins ⊆ MCL_CURRENT, converging to just MCL_CURRENT as we fault
-             * in pages.
-             */
-            /* CAP_IPC_LOCK required */
-            if (mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) && (errno != EINVAL)) {
-                ALOGW("mlockall failed %s", strerror(errno));
-            }
-
-            /* CAP_NICE required */
-            if (sched_setscheduler(0, SCHED_FIFO, &param)) {
-                ALOGW("set SCHED_FIFO failed %s", strerror(errno));
-            }
-        }
-
-        mainloop();
-    }
-
-#ifdef LMKD_LOG_STATS
-    statslog_destroy(&log_ctx);
-#endif
-
-    android_log_destroy(&ctx);
-
-    ALOGI("exiting");
-    return 0;
-}
diff --git a/lmkd/lmkd.rc b/lmkd/lmkd.rc
deleted file mode 100644
index 76b6055..0000000
--- a/lmkd/lmkd.rc
+++ /dev/null
@@ -1,8 +0,0 @@
-service lmkd /system/bin/lmkd
-    class core
-    user lmkd
-    group lmkd system readproc
-    capabilities DAC_OVERRIDE KILL IPC_LOCK SYS_NICE SYS_RESOURCE
-    critical
-    socket lmkd seqpacket 0660 system system
-    writepid /dev/cpuset/system-background/tasks
diff --git a/lmkd/statslog.c b/lmkd/statslog.c
deleted file mode 100644
index 0c230ae..0000000
--- a/lmkd/statslog.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *  Copyright 2018 Google, Inc
- *
- *  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 <assert.h>
-#include <errno.h>
-#include <log/log_id.h>
-#include <stats_event_list.h>
-#include <time.h>
-
-static int64_t getElapsedRealTimeNs() {
-    struct timespec t;
-    t.tv_sec = t.tv_nsec = 0;
-    clock_gettime(CLOCK_BOOTTIME, &t);
-    return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;
-}
-
-/**
- * Logs the change in LMKD state which is used as start/stop boundaries for logging
- * LMK_KILL_OCCURRED event.
- * Code: LMK_STATE_CHANGED = 54
- */
-int
-stats_write_lmk_state_changed(android_log_context ctx, int32_t code, int32_t state) {
-    assert(ctx != NULL);
-    int ret = -EINVAL;
-    if (!ctx) {
-        return ret;
-    }
-
-    reset_log_context(ctx);
-
-    if ((ret = android_log_write_int64(ctx, getElapsedRealTimeNs())) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int32(ctx, code)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int32(ctx, state)) < 0) {
-        return ret;
-    }
-
-    return write_to_logger(ctx, LOG_ID_STATS);
-}
-
-/**
- * Logs the event when LMKD kills a process to reduce memory pressure.
- * Code: LMK_KILL_OCCURRED = 51
- */
-int
-stats_write_lmk_kill_occurred(android_log_context ctx, int32_t code, int32_t uid,
-                              char const* process_name, int32_t oom_score, int64_t pgfault,
-                              int64_t pgmajfault, int64_t rss_in_bytes, int64_t cache_in_bytes,
-                              int64_t swap_in_bytes, int64_t process_start_time_ns,
-                              int32_t min_oom_score) {
-    assert(ctx != NULL);
-    int ret = -EINVAL;
-    if (!ctx) {
-        return ret;
-    }
-    reset_log_context(ctx);
-
-    if ((ret = android_log_write_int64(ctx, getElapsedRealTimeNs())) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int32(ctx, code)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int32(ctx, uid)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_string8(ctx, (process_name == NULL) ? "" : process_name)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int32(ctx, oom_score)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int64(ctx, pgfault)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int64(ctx, pgmajfault)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int64(ctx, rss_in_bytes)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int64(ctx, cache_in_bytes)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int64(ctx, swap_in_bytes)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int64(ctx, process_start_time_ns)) < 0) {
-        return ret;
-    }
-
-    if ((ret = android_log_write_int32(ctx, min_oom_score)) < 0) {
-        return ret;
-    }
-
-    return write_to_logger(ctx, LOG_ID_STATS);
-}
diff --git a/lmkd/statslog.h b/lmkd/statslog.h
deleted file mode 100644
index 2edba7a..0000000
--- a/lmkd/statslog.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  Copyright 2018 Google, Inc
- *
- *  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 _STATSLOG_H_
-#define _STATSLOG_H_
-
-#include <assert.h>
-#include <stats_event_list.h>
-#include <stdbool.h>
-#include <sys/cdefs.h>
-
-#include <cutils/properties.h>
-
-__BEGIN_DECLS
-
-/*
- * These are defined in
- * http://cs/android/frameworks/base/cmds/statsd/src/atoms.proto
- */
-#define LMK_KILL_OCCURRED 51
-#define LMK_STATE_CHANGED 54
-#define LMK_STATE_CHANGE_START 1
-#define LMK_STATE_CHANGE_STOP 2
-
-/*
- * The single event tag id for all stats logs.
- * Keep this in sync with system/core/logcat/event.logtags
- */
-const static int kStatsEventTag = 1937006964;
-
-static inline void statslog_init(android_log_context* log_ctx, bool* enable_stats_log) {
-    assert(log_ctx != NULL);
-    assert(enable_stats_log != NULL);
-    *enable_stats_log = property_get_bool("ro.lmk.log_stats", false);
-
-    if (*enable_stats_log) {
-        *log_ctx = create_android_logger(kStatsEventTag);
-    }
-}
-
-static inline void statslog_destroy(android_log_context* log_ctx) {
-    assert(log_ctx != NULL);
-    if (*log_ctx) {
-        android_log_destroy(log_ctx);
-    }
-}
-
-struct memory_stat {
-    int64_t pgfault;
-    int64_t pgmajfault;
-    int64_t rss_in_bytes;
-    int64_t cache_in_bytes;
-    int64_t swap_in_bytes;
-    int64_t process_start_time_ns;
-};
-
-#define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat"
-#define PROC_STAT_FILE_PATH "/proc/%d/stat"
-#define PROC_STAT_BUFFER_SIZE 1024
-#define BYTES_IN_KILOBYTE 1024
-
-/**
- * Logs the change in LMKD state which is used as start/stop boundaries for logging
- * LMK_KILL_OCCURRED event.
- * Code: LMK_STATE_CHANGED = 54
- */
-int
-stats_write_lmk_state_changed(android_log_context ctx, int32_t code, int32_t state);
-
-/**
- * Logs the event when LMKD kills a process to reduce memory pressure.
- * Code: LMK_KILL_OCCURRED = 51
- */
-int
-stats_write_lmk_kill_occurred(android_log_context ctx, int32_t code, int32_t uid,
-                              char const* process_name, int32_t oom_score, int64_t pgfault,
-                              int64_t pgmajfault, int64_t rss_in_bytes, int64_t cache_in_bytes,
-                              int64_t swap_in_bytes, int64_t process_start_time_ns,
-                              int32_t min_oom_score);
-
-__END_DECLS
-
-#endif /* _STATSLOG_H_ */
diff --git a/lmkd/tests/Android.bp b/lmkd/tests/Android.bp
deleted file mode 100644
index 4e845fd..0000000
--- a/lmkd/tests/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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.
-
-cc_test {
-    name: "lmkd_unit_test",
-
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-    ],
-
-    static_libs: [
-        "liblmkd_utils",
-    ],
-
-    target: {
-        android: {
-            srcs: ["lmkd_test.cpp"],
-        },
-    },
-
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-
-    compile_multilib: "first",
-}
diff --git a/lmkd/tests/lmkd_test.cpp b/lmkd/tests/lmkd_test.cpp
deleted file mode 100644
index f54b25c..0000000
--- a/lmkd/tests/lmkd_test.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * 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.
- */
-
-#include <sstream>
-#include <stdio.h>
-#include <string.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#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 <gtest/gtest.h>
-#include <lmkd.h>
-#include <liblmkd_utils.h>
-#include <log/log_properties.h>
-#include <private/android_filesystem_config.h>
-
-using namespace android::base;
-
-#define INKERNEL_MINFREE_PATH "/sys/module/lowmemorykiller/parameters/minfree"
-#define LMKDTEST_RESPAWN_FLAG "LMKDTEST_RESPAWN"
-
-#define LMKD_LOGCAT_MARKER "lowmemorykiller"
-#define LMKD_KILL_MARKER_TEMPLATE LMKD_LOGCAT_MARKER ": Kill '%s'"
-#define OOM_MARKER "Out of memory"
-#define OOM_KILL_MARKER "Killed process"
-#define MIN_LOG_SIZE 100
-
-#define ONE_MB (1 << 20)
-
-/* Test constant parameters */
-#define OOM_ADJ_MAX 1000
-#define OOM_ADJ_MIN 0
-#define OOM_ADJ_STEP 100
-#define STEP_COUNT ((OOM_ADJ_MAX - OOM_ADJ_MIN) / OOM_ADJ_STEP + 1)
-
-#define ALLOC_STEP (ONE_MB)
-#define ALLOC_DELAY 1000
-
-/* Utility functions */
-std::string readCommand(const std::string& command) {
-    FILE* fp = popen(command.c_str(), "r");
-    std::string content;
-    ReadFdToString(fileno(fp), &content);
-    pclose(fp);
-    return content;
-}
-
-std::string readLogcat(const std::string& marker) {
-    std::string content = readCommand("logcat -d -b all");
-    size_t pos = content.find(marker);
-    if (pos == std::string::npos) return "";
-    content.erase(0, pos);
-    return content;
-}
-
-bool writeFile(const std::string& file, const std::string& string) {
-    if (getuid() == static_cast<unsigned>(AID_ROOT)) {
-        return WriteStringToFile(string, file);
-    }
-    return string == readCommand(
-        "echo -n '" + string + "' | su root tee " + file + " 2>&1");
-}
-
-bool writeKmsg(const std::string& marker) {
-    return writeFile("/dev/kmsg", marker);
-}
-
-std::string getTextAround(const std::string& text, size_t pos,
-                          size_t lines_before, size_t lines_after) {
-    size_t start_pos = pos;
-
-    // find start position
-    // move up lines_before number of lines
-    while (lines_before > 0 &&
-           (start_pos = text.rfind('\n', start_pos)) != std::string::npos) {
-        lines_before--;
-    }
-    // move to the beginning of the line
-    start_pos = text.rfind('\n', start_pos);
-    start_pos = (start_pos == std::string::npos) ? 0 : start_pos + 1;
-
-    // find end position
-    // move down lines_after number of lines
-    while (lines_after > 0 &&
-           (pos = text.find('\n', pos)) != std::string::npos) {
-        pos++;
-        lines_after--;
-    }
-    return text.substr(start_pos, (pos == std::string::npos) ?
-                       std::string::npos : pos - start_pos);
-}
-
-bool getExecPath(std::string &path) {
-    char buf[PATH_MAX + 1];
-    int ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
-    if (ret < 0) {
-        return false;
-    }
-    buf[ret] = '\0';
-    path = buf;
-    return true;
-}
-
-/* Child synchronization primitives */
-#define STATE_INIT 0
-#define STATE_CHILD_READY 1
-#define STATE_PARENT_READY 2
-
-struct state_sync {
-    pthread_mutex_t mutex;
-    pthread_cond_t condition;
-    int state;
-};
-
-struct state_sync * init_state_sync_obj() {
-    struct state_sync *ssync;
-
-    ssync = (struct state_sync*)mmap(NULL, sizeof(struct state_sync),
-                PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
-    if (ssync == MAP_FAILED) {
-        return NULL;
-    }
-
-    pthread_mutexattr_t mattr;
-    pthread_mutexattr_init(&mattr);
-    pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
-    pthread_mutex_init(&ssync->mutex, &mattr);
-
-    pthread_condattr_t cattr;
-    pthread_condattr_init(&cattr);
-    pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
-    pthread_cond_init(&ssync->condition, &cattr);
-
-    ssync->state = STATE_INIT;
-    return ssync;
-}
-
-void destroy_state_sync_obj(struct state_sync *ssync) {
-    pthread_cond_destroy(&ssync->condition);
-    pthread_mutex_destroy(&ssync->mutex);
-    munmap(ssync, sizeof(struct state_sync));
-}
-
-void signal_state(struct state_sync *ssync, int state) {
-    pthread_mutex_lock(&ssync->mutex);
-    ssync->state = state;
-    pthread_cond_signal(&ssync->condition);
-    pthread_mutex_unlock(&ssync->mutex);
-}
-
-void wait_for_state(struct state_sync *ssync, int state) {
-    pthread_mutex_lock(&ssync->mutex);
-    while (ssync->state != state) {
-        pthread_cond_wait(&ssync->condition, &ssync->mutex);
-    }
-    pthread_mutex_unlock(&ssync->mutex);
-}
-
-/* Memory allocation and data sharing */
-struct shared_data {
-    size_t allocated;
-    bool finished;
-    size_t total_size;
-    size_t step_size;
-    size_t step_delay;
-    int oomadj;
-};
-
-volatile void *gptr;
-void add_pressure(struct shared_data *data) {
-    volatile void *ptr;
-    size_t allocated_size = 0;
-
-    data->finished = false;
-    while (allocated_size < data->total_size) {
-        ptr = mmap(NULL, data->step_size, PROT_READ | PROT_WRITE,
-                MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
-        if (ptr != MAP_FAILED) {
-            /* create ptr aliasing to prevent compiler optimizing the access */
-            gptr = ptr;
-            /* make data non-zero */
-            memset((void*)ptr, (int)(allocated_size + 1), data->step_size);
-            allocated_size += data->step_size;
-            data->allocated = allocated_size;
-        }
-        usleep(data->step_delay);
-    }
-    data->finished = (allocated_size >= data->total_size);
-}
-
-/* Memory stress test main body */
-void runMemStressTest() {
-    struct shared_data *data;
-    struct state_sync *ssync;
-    int sock;
-    pid_t pid;
-    uid_t uid = getuid();
-
-    // check if in-kernel LMK driver is present
-    if (!access(INKERNEL_MINFREE_PATH, W_OK)) {
-        GTEST_LOG_(INFO) << "Must not have kernel lowmemorykiller driver,"
-                         << " terminating test";
-        return;
-    }
-
-    ASSERT_FALSE((sock = lmkd_connect()) < 0)
-        << "Failed to connect to lmkd process, err=" << strerror(errno);
-
-    /* allocate shared memory to communicate params with a child */
-    data = (struct shared_data*)mmap(NULL, sizeof(struct shared_data),
-                PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
-    ASSERT_FALSE(data == MAP_FAILED) << "Memory allocation failure";
-    data->total_size = (size_t)-1; /* allocate until killed */
-    data->step_size = ALLOC_STEP;
-    data->step_delay = ALLOC_DELAY;
-
-    /* allocate state sync object */
-    ASSERT_FALSE((ssync = init_state_sync_obj()) == NULL)
-        << "Memory allocation failure";
-
-    /* run the test gradually decreasing oomadj */
-    data->oomadj = OOM_ADJ_MAX;
-    while (data->oomadj >= OOM_ADJ_MIN) {
-        ASSERT_FALSE((pid = fork()) < 0)
-            << "Failed to spawn a child process, err=" << strerror(errno);
-        if (pid != 0) {
-            /* Parent */
-            struct lmk_procprio params;
-            /* wait for child to start and get ready */
-            wait_for_state(ssync, STATE_CHILD_READY);
-            params.pid = pid;
-            params.uid = uid;
-            params.oomadj = data->oomadj;
-            ASSERT_FALSE(lmkd_register_proc(sock, &params) < 0)
-                << "Failed to communicate with lmkd, err=" << strerror(errno);
-            // signal the child it can proceed
-            signal_state(ssync, STATE_PARENT_READY);
-            waitpid(pid, NULL, 0);
-            if (data->finished) {
-                GTEST_LOG_(INFO) << "Child [pid=" << pid << "] allocated "
-                                 << data->allocated / ONE_MB << "MB";
-            } else {
-                GTEST_LOG_(INFO) << "Child [pid=" << pid << "] allocated "
-                                 << data->allocated / ONE_MB
-                                 << "MB before being killed";
-            }
-            data->oomadj -= OOM_ADJ_STEP;
-        } else {
-            /* Child */
-            pid = getpid();
-            GTEST_LOG_(INFO) << "Child [pid=" << pid
-                             << "] is running at oomadj="
-                             << data->oomadj;
-            data->allocated = 0;
-            data->finished = false;
-            ASSERT_FALSE(create_memcg(uid, pid) != 0)
-                << "Child [pid=" << pid << "] failed to create a cgroup";
-            signal_state(ssync, STATE_CHILD_READY);
-            wait_for_state(ssync, STATE_PARENT_READY);
-            add_pressure(data);
-            /* should not reach here, child should be killed by OOM/LMK */
-            FAIL() << "Child [pid=" << pid << "] was not killed";
-            break;
-        }
-    }
-    destroy_state_sync_obj(ssync);
-    munmap(data, sizeof(struct shared_data));
-    close(sock);
-}
-
-TEST(lmkd, check_for_oom) {
-    // test requirements
-    //   userdebug build
-    if (!__android_log_is_debuggable()) {
-        GTEST_LOG_(INFO) << "Must be userdebug build, terminating test";
-        return;
-    }
-
-    // if respawned test process then run the test and exit (no analysis)
-    if (getenv(LMKDTEST_RESPAWN_FLAG) != NULL) {
-        runMemStressTest();
-        return;
-    }
-
-    // Main test process
-    // mark the beginning of the test
-    std::string marker = StringPrintf(
-        "LMKD test start %lu\n", static_cast<unsigned long>(time(nullptr)));
-    ASSERT_TRUE(writeKmsg(marker));
-
-    // get executable complete path
-    std::string test_path;
-    ASSERT_TRUE(getExecPath(test_path));
-
-    std::string test_output;
-    if (getuid() != static_cast<unsigned>(AID_ROOT)) {
-        // if not root respawn itself as root and capture output
-        std::string command = StringPrintf(
-            "%s=true su root %s 2>&1", LMKDTEST_RESPAWN_FLAG,
-            test_path.c_str());
-        std::string test_output = readCommand(command);
-        GTEST_LOG_(INFO) << test_output;
-    } else {
-        // main test process is root, run the test
-        runMemStressTest();
-    }
-
-    // Analyze results
-    // capture logcat containind kernel logs
-    std::string logcat_out = readLogcat(marker);
-
-    // 1. extract LMKD kills from logcat output, count kills
-    std::stringstream kill_logs;
-    int hit_count = 0;
-    size_t pos = 0;
-    marker = StringPrintf(LMKD_KILL_MARKER_TEMPLATE, test_path.c_str());
-
-    while (true) {
-        if ((pos = logcat_out.find(marker, pos)) != std::string::npos) {
-            kill_logs << getTextAround(logcat_out, pos, 0, 1);
-            pos += marker.length();
-            hit_count++;
-        } else {
-            break;
-        }
-    }
-    GTEST_LOG_(INFO) << "====Logged kills====" << std::endl
-                     << kill_logs.str();
-    EXPECT_TRUE(hit_count == STEP_COUNT) << "Number of kills " << hit_count
-                                         << " is less than expected "
-                                         << STEP_COUNT;
-
-    // 2. check kernel logs for OOM kills
-    pos = logcat_out.find(OOM_MARKER);
-    bool oom_detected = (pos != std::string::npos);
-    bool oom_kill_detected = (oom_detected &&
-        logcat_out.find(OOM_KILL_MARKER, pos) != std::string::npos);
-
-    EXPECT_FALSE(oom_kill_detected) << "OOM kill is detected!";
-    if (oom_detected || oom_kill_detected) {
-        // capture logcat with logs around all OOMs
-        pos = 0;
-        while ((pos = logcat_out.find(OOM_MARKER, pos)) != std::string::npos) {
-            GTEST_LOG_(INFO) << "====Logs around OOM====" << std::endl
-                             << getTextAround(logcat_out, pos,
-                                    MIN_LOG_SIZE / 2, MIN_LOG_SIZE / 2);
-            pos += strlen(OOM_MARKER);
-        }
-    }
-
-    // output complete logcat with kernel (might get truncated)
-    GTEST_LOG_(INFO) << "====Complete logcat output====" << std::endl
-                     << logcat_out;
-}
-
diff --git a/logcat/Android.bp b/logcat/Android.bp
index 5030b15..61fba59 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -21,10 +21,10 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION=1",
     ],
     shared_libs: [
         "libbase",
-        "libpcrecpp",
         "libprocessgroup",
     ],
     static_libs: ["liblog"],
@@ -36,31 +36,22 @@
 
     defaults: ["logcat_defaults"],
     srcs: [
-        "logcat_main.cpp",
         "logcat.cpp",
     ],
 }
 
-cc_binary {
+sh_binary {
     name: "logcatd",
-
-    defaults: ["logcat_defaults"],
-    srcs: [
-        "logcatd_main.cpp",
-        "logcat.cpp",
-    ],
+    src: "logcatd",
 }
 
-cc_prebuilt_binary {
+sh_binary {
     name: "logpersist.start",
-    srcs: ["logpersist"],
+    src: "logpersist",
     init_rc: ["logcatd.rc"],
     required: ["logcatd"],
     symlinks: [
         "logpersist.stop",
         "logpersist.cat",
     ],
-    strip: {
-        none: true,
-    },
 }
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 15e07fe..7b18438 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -14,255 +14,137 @@
  * limitations under the License.
  */
 
-#include "logcat.h"
-
-#include <android-base/macros.h>
-#include <arpa/inet.h>
-#include <assert.h>
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
+#include <error.h>
 #include <fcntl.h>
 #include <getopt.h>
 #include <math.h>
-#include <pthread.h>
 #include <sched.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/cdefs.h>
+#include <sys/ioctl.h>
 #include <sys/resource.h>
-#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
-#include <atomic>
 #include <memory>
+#include <regex>
 #include <string>
 #include <utility>
 #include <vector>
 
 #include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
-#include <cutils/sockets.h>
+#include <android-base/unique_fd.h>
+#include <android/log.h>
 #include <log/event_tag_map.h>
+#include <log/log_id.h>
 #include <log/logprint.h>
 #include <private/android_logger.h>
 #include <processgroup/sched_policy.h>
 #include <system/thread_defs.h>
 
-#include <pcrecpp.h>
-
 #define DEFAULT_MAX_ROTATED_LOGS 4
 
-struct log_device_t {
-    const char* device;
-    bool binary;
-    struct logger* logger;
-    struct logger_list* logger_list;
-    bool printed;
+using android::base::Join;
+using android::base::ParseByteCount;
+using android::base::ParseUint;
+using android::base::Split;
+using android::base::StringPrintf;
 
-    log_device_t* next;
+class Logcat {
+  public:
+    int Run(int argc, char** argv);
 
-    log_device_t(const char* d, bool b) {
-        device = d;
-        binary = b;
-        next = nullptr;
-        printed = false;
-        logger = nullptr;
-        logger_list = nullptr;
-    }
+  private:
+    void RotateLogs();
+    void ProcessBuffer(struct log_msg* buf);
+    void PrintDividers(log_id_t log_id, bool print_dividers);
+    void SetupOutputAndSchedulingPolicy(bool blocking);
+    int SetLogFormat(const char* format_string);
+
+    // Used for all options
+    android::base::unique_fd output_fd_{dup(STDOUT_FILENO)};
+    std::unique_ptr<AndroidLogFormat, decltype(&android_log_format_free)> logformat_{
+            android_log_format_new(), &android_log_format_free};
+
+    // For logging to a file and log rotation
+    const char* output_file_name_ = nullptr;
+    size_t log_rotate_size_kb_ = 0;                       // 0 means "no log rotation"
+    size_t max_rotated_logs_ = DEFAULT_MAX_ROTATED_LOGS;  // 0 means "unbounded"
+    size_t out_byte_count_ = 0;
+
+    // For binary log buffers
+    int print_binary_ = 0;
+    std::unique_ptr<EventTagMap, decltype(&android_closeEventTagMap)> event_tag_map_{
+            nullptr, &android_closeEventTagMap};
+    bool has_opened_event_tag_map_ = false;
+
+    // For the related --regex, --max-count, --print
+    std::unique_ptr<std::regex> regex_;
+    size_t max_count_ = 0;  // 0 means "infinite"
+    size_t print_count_ = 0;
+    bool print_it_anyways_ = false;
+
+    // For PrintDividers()
+    log_id_t last_printed_id_ = LOG_ID_MAX;
+    bool printed_start_[LOG_ID_MAX] = {};
+
+    bool debug_ = false;
 };
 
-struct android_logcat_context_internal {
-    // status
-    volatile std::atomic_int retval;  // valid if thread_stopped set
-    // Arguments passed in, or copies and storage thereof if a thread.
-    int argc;
-    char* const* argv;
-    char* const* envp;
-    std::vector<std::string> args;
-    std::vector<const char*> argv_hold;
-    std::vector<std::string> envs;
-    std::vector<const char*> envp_hold;
-    int output_fd;  // duplication of fileno(output) (below)
-    int error_fd;   // duplication of fileno(error) (below)
+#ifndef F2FS_IOC_SET_PIN_FILE
+#define F2FS_IOCTL_MAGIC       0xf5
+#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
+#endif
 
-    // library
-    int fds[2];    // From popen call
-    FILE* output;  // everything writes to fileno(output), buffer unused
-    FILE* error;   // unless error == output.
-    pthread_t thr;
-    volatile std::atomic_bool stop;  // quick exit flag
-    volatile std::atomic_bool thread_stopped;
-    bool stderr_null;    // shell "2>/dev/null"
-    bool stderr_stdout;  // shell "2>&1"
+static int openLogFile(const char* pathname, size_t sizeKB) {
+    int fd = open(pathname, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
+    if (fd < 0) {
+        return fd;
+    }
 
-    // global variables
-    AndroidLogFormat* logformat;
-    const char* outputFileName;
-    // 0 means "no log rotation"
-    size_t logRotateSizeKBytes;
-    // 0 means "unbounded"
-    size_t maxRotatedLogs;
-    size_t outByteCount;
-    int printBinary;
-    int devCount;  // >1 means multiple
-    pcrecpp::RE* regex;
-    log_device_t* devices;
-    EventTagMap* eventTagMap;
-    // 0 means "infinite"
-    size_t maxCount;
-    size_t printCount;
-
-    bool printItAnyways;
-    bool debug;
-    bool hasOpenedEventTagMap;
-};
-
-// Creates a context associated with this logcat instance
-android_logcat_context create_android_logcat() {
-    android_logcat_context_internal* context;
-
-    context = (android_logcat_context_internal*)calloc(
-        1, sizeof(android_logcat_context_internal));
-    if (!context) return nullptr;
-
-    context->fds[0] = -1;
-    context->fds[1] = -1;
-    context->output_fd = -1;
-    context->error_fd = -1;
-    context->maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS;
-
-    context->argv_hold.clear();
-    context->args.clear();
-    context->envp_hold.clear();
-    context->envs.clear();
-
-    return (android_logcat_context)context;
+    // no need to check errors
+    __u32 set = 1;
+    ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);
+    fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, (sizeKB << 10));
+    return fd;
 }
 
-// logd prefixes records with a length field
-#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
-
-namespace android {
-
-enum helpType { HELP_FALSE, HELP_TRUE, HELP_FORMAT };
-
-// if showHelp is set, newline required in fmt statement to transition to usage
-static void logcat_panic(android_logcat_context_internal* context,
-                         enum helpType showHelp, const char* fmt, ...)
-    __printflike(3, 4);
-
-static int openLogFile(const char* pathname) {
-    return open(pathname, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
-}
-
-static void close_output(android_logcat_context_internal* context) {
-    // split output_from_error
-    if (context->error == context->output) {
-        context->output = nullptr;
-        context->output_fd = -1;
-    }
-    if (context->error && (context->output_fd == fileno(context->error))) {
-        context->output_fd = -1;
-    }
-    if (context->output_fd == context->error_fd) {
-        context->output_fd = -1;
-    }
-    // close output channel
-    if (context->output) {
-        if (context->output != stdout) {
-            if (context->output_fd == fileno(context->output)) {
-                context->output_fd = -1;
-            }
-            if (context->fds[1] == fileno(context->output)) {
-                context->fds[1] = -1;
-            }
-            fclose(context->output);
-        }
-        context->output = nullptr;
-    }
-    if (context->output_fd >= 0) {
-        if (context->output_fd != fileno(stdout)) {
-            if (context->fds[1] == context->output_fd) {
-                context->fds[1] = -1;
-            }
-            close(context->output_fd);
-        }
-        context->output_fd = -1;
-    }
-}
-
-static void close_error(android_logcat_context_internal* context) {
-    // split error_from_output
-    if (context->output == context->error) {
-        context->error = nullptr;
-        context->error_fd = -1;
-    }
-    if (context->output && (context->error_fd == fileno(context->output))) {
-        context->error_fd = -1;
-    }
-    if (context->error_fd == context->output_fd) {
-        context->error_fd = -1;
-    }
-    // close error channel
-    if (context->error) {
-        if ((context->error != stderr) && (context->error != stdout)) {
-            if (context->error_fd == fileno(context->error)) {
-                context->error_fd = -1;
-            }
-            if (context->fds[1] == fileno(context->error)) {
-                context->fds[1] = -1;
-            }
-            fclose(context->error);
-        }
-        context->error = nullptr;
-    }
-    if (context->error_fd >= 0) {
-        if ((context->error_fd != fileno(stdout)) &&
-            (context->error_fd != fileno(stderr))) {
-            if (context->fds[1] == context->error_fd) context->fds[1] = -1;
-            close(context->error_fd);
-        }
-        context->error_fd = -1;
-    }
-}
-
-static void rotateLogs(android_logcat_context_internal* context) {
-    int err;
-
+void Logcat::RotateLogs() {
     // Can't rotate logs if we're not outputting to a file
-    if (!context->outputFileName) return;
+    if (!output_file_name_) return;
 
-    close_output(context);
+    output_fd_.reset();
 
     // Compute the maximum number of digits needed to count up to
     // maxRotatedLogs in decimal.  eg:
     // maxRotatedLogs == 30
     //   -> log10(30) == 1.477
     //   -> maxRotationCountDigits == 2
-    int maxRotationCountDigits =
-        (context->maxRotatedLogs > 0)
-            ? (int)(floor(log10(context->maxRotatedLogs) + 1))
-            : 0;
+    int max_rotation_count_digits =
+            max_rotated_logs_ > 0 ? (int)(floor(log10(max_rotated_logs_) + 1)) : 0;
 
-    for (int i = context->maxRotatedLogs; i > 0; i--) {
-        std::string file1 = android::base::StringPrintf(
-            "%s.%.*d", context->outputFileName, maxRotationCountDigits, i);
+    for (int i = max_rotated_logs_; i > 0; i--) {
+        std::string file1 =
+                StringPrintf("%s.%.*d", output_file_name_, max_rotation_count_digits, i);
 
         std::string file0;
         if (!(i - 1)) {
-            file0 = android::base::StringPrintf("%s", context->outputFileName);
+            file0 = output_file_name_;
         } else {
-            file0 =
-                android::base::StringPrintf("%s.%.*d", context->outputFileName,
-                                            maxRotationCountDigits, i - 1);
+            file0 = StringPrintf("%s.%.*d", output_file_name_, max_rotation_count_digits, i - 1);
         }
 
         if (!file0.length() || !file1.length()) {
@@ -270,238 +152,200 @@
             break;
         }
 
-        err = rename(file0.c_str(), file1.c_str());
+        int err = rename(file0.c_str(), file1.c_str());
 
         if (err < 0 && errno != ENOENT) {
             perror("while rotating log files");
         }
     }
 
-    context->output_fd = openLogFile(context->outputFileName);
+    output_fd_.reset(openLogFile(output_file_name_, log_rotate_size_kb_));
 
-    if (context->output_fd < 0) {
-        logcat_panic(context, HELP_FALSE, "couldn't open output file");
-        return;
-    }
-    context->output = fdopen(context->output_fd, "web");
-    if (!context->output) {
-        logcat_panic(context, HELP_FALSE, "couldn't fdopen output file");
-        return;
-    }
-    if (context->stderr_stdout) {
-        close_error(context);
-        context->error = context->output;
-        context->error_fd = context->output_fd;
+    if (!output_fd_.ok()) {
+        error(EXIT_FAILURE, errno, "Couldn't open output file");
     }
 
-    context->outByteCount = 0;
+    out_byte_count_ = 0;
 }
 
-void printBinary(android_logcat_context_internal* context, struct log_msg* buf) {
-    size_t size = buf->len();
-
-    TEMP_FAILURE_RETRY(write(context->output_fd, buf, size));
-}
-
-static bool regexOk(android_logcat_context_internal* context,
-                    const AndroidLogEntry& entry) {
-    if (!context->regex) return true;
-
-    std::string messageString(entry.message, entry.messageLen);
-
-    return context->regex->PartialMatch(messageString);
-}
-
-static void processBuffer(android_logcat_context_internal* context,
-                          log_device_t* dev, struct log_msg* buf) {
+void Logcat::ProcessBuffer(struct log_msg* buf) {
     int bytesWritten = 0;
     int err;
     AndroidLogEntry entry;
     char binaryMsgBuf[1024];
 
-    if (dev->binary) {
-        if (!context->eventTagMap && !context->hasOpenedEventTagMap) {
-            context->eventTagMap = android_openEventTagMap(nullptr);
-            context->hasOpenedEventTagMap = true;
+    bool is_binary =
+            buf->id() == LOG_ID_EVENTS || buf->id() == LOG_ID_STATS || buf->id() == LOG_ID_SECURITY;
+
+    if (is_binary) {
+        if (!event_tag_map_ && !has_opened_event_tag_map_) {
+            event_tag_map_.reset(android_openEventTagMap(nullptr));
+            has_opened_event_tag_map_ = true;
         }
-        err = android_log_processBinaryLogBuffer(
-            &buf->entry_v1, &entry, context->eventTagMap, binaryMsgBuf,
-            sizeof(binaryMsgBuf));
+        err = android_log_processBinaryLogBuffer(&buf->entry, &entry, event_tag_map_.get(),
+                                                 binaryMsgBuf, sizeof(binaryMsgBuf));
         // printf(">>> pri=%d len=%d msg='%s'\n",
         //    entry.priority, entry.messageLen, entry.message);
     } else {
-        err = android_log_processLogBuffer(&buf->entry_v1, &entry);
+        err = android_log_processLogBuffer(&buf->entry, &entry);
     }
-    if ((err < 0) && !context->debug) return;
+    if (err < 0 && !debug_) return;
 
-    if (android_log_shouldPrintLine(
-            context->logformat, std::string(entry.tag, entry.tagLen).c_str(),
-            entry.priority)) {
-        bool match = regexOk(context, entry);
+    if (android_log_shouldPrintLine(logformat_.get(), std::string(entry.tag, entry.tagLen).c_str(),
+                                    entry.priority)) {
+        bool match = !regex_ ||
+                     std::regex_search(entry.message, entry.message + entry.messageLen, *regex_);
 
-        context->printCount += match;
-        if (match || context->printItAnyways) {
-            bytesWritten = android_log_printLogLine(context->logformat,
-                                                    context->output_fd, &entry);
+        print_count_ += match;
+        if (match || print_it_anyways_) {
+            bytesWritten = android_log_printLogLine(logformat_.get(), output_fd_.get(), &entry);
 
             if (bytesWritten < 0) {
-                logcat_panic(context, HELP_FALSE, "output error");
-                return;
+                error(EXIT_FAILURE, 0, "Output error.");
             }
         }
     }
 
-    context->outByteCount += bytesWritten;
+    out_byte_count_ += bytesWritten;
 
-    if (context->logRotateSizeKBytes > 0 &&
-        (context->outByteCount / 1024) >= context->logRotateSizeKBytes) {
-        rotateLogs(context);
+    if (log_rotate_size_kb_ > 0 && (out_byte_count_ / 1024) >= log_rotate_size_kb_) {
+        RotateLogs();
     }
 }
 
-static void maybePrintStart(android_logcat_context_internal* context,
-                            log_device_t* dev, bool printDividers) {
-    if (!dev->printed || printDividers) {
-        if (context->devCount > 1 && !context->printBinary) {
-            char buf[1024];
-            snprintf(buf, sizeof(buf), "--------- %s %s\n",
-                     dev->printed ? "switch to" : "beginning of", dev->device);
-            if (write(context->output_fd, buf, strlen(buf)) < 0) {
-                logcat_panic(context, HELP_FALSE, "output error");
-                return;
-            }
+void Logcat::PrintDividers(log_id_t log_id, bool print_dividers) {
+    if (log_id == last_printed_id_ || print_binary_) {
+        return;
+    }
+    if (!printed_start_[log_id] || print_dividers) {
+        if (dprintf(output_fd_.get(), "--------- %s %s\n",
+                    printed_start_[log_id] ? "switch to" : "beginning of",
+                    android_log_id_to_name(log_id)) < 0) {
+            error(EXIT_FAILURE, errno, "Output error");
         }
-        dev->printed = true;
     }
+    last_printed_id_ = log_id;
+    printed_start_[log_id] = true;
 }
 
-static void setupOutputAndSchedulingPolicy(
-    android_logcat_context_internal* context, bool blocking) {
-    if (!context->outputFileName) return;
+void Logcat::SetupOutputAndSchedulingPolicy(bool blocking) {
+    if (!output_file_name_) return;
 
     if (blocking) {
         // Lower priority and set to batch scheduling if we are saving
         // the logs into files and taking continuous content.
-        if ((set_sched_policy(0, SP_BACKGROUND) < 0) && context->error) {
-            fprintf(context->error,
-                    "failed to set background scheduling policy\n");
+        if (set_sched_policy(0, SP_BACKGROUND) < 0) {
+            fprintf(stderr, "failed to set background scheduling policy\n");
         }
 
-        struct sched_param param;
-        memset(&param, 0, sizeof(param));
+        struct sched_param param = {};
         if (sched_setscheduler((pid_t)0, SCHED_BATCH, &param) < 0) {
             fprintf(stderr, "failed to set to batch scheduler\n");
         }
 
-        if ((setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) &&
-            context->error) {
-            fprintf(context->error, "failed set to priority\n");
+        if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
+            fprintf(stderr, "failed set to priority\n");
         }
     }
 
-    close_output(context);
+    output_fd_.reset(openLogFile(output_file_name_, log_rotate_size_kb_));
 
-    context->output_fd = openLogFile(context->outputFileName);
-
-    if (context->output_fd < 0) {
-        logcat_panic(context, HELP_FALSE, "couldn't open output file");
-        return;
+    if (!output_fd_.ok()) {
+        error(EXIT_FAILURE, errno, "Couldn't open output file");
     }
 
     struct stat statbuf;
-    if (fstat(context->output_fd, &statbuf) == -1) {
-        close_output(context);
-        logcat_panic(context, HELP_FALSE, "couldn't get output file stat\n");
-        return;
+    if (fstat(output_fd_.get(), &statbuf) == -1) {
+        error(EXIT_FAILURE, errno, "Couldn't get output file stat");
     }
 
     if ((size_t)statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
-        close_output(context);
-        logcat_panic(context, HELP_FALSE, "invalid output file stat\n");
-        return;
+        error(EXIT_FAILURE, 0, "Invalid output file stat.");
     }
 
-    context->output = fdopen(context->output_fd, "web");
-
-    context->outByteCount = statbuf.st_size;
+    out_byte_count_ = statbuf.st_size;
 }
 
 // clang-format off
-static void show_help(android_logcat_context_internal* context) {
-    if (!context->error) return;
+static void show_help() {
+    const char* cmd = getprogname();
 
-    const char* cmd = strrchr(context->argv[0], '/');
-    cmd = cmd ? cmd + 1 : context->argv[0];
+    fprintf(stderr, "Usage: %s [options] [filterspecs]\n", cmd);
 
-    fprintf(context->error, "Usage: %s [options] [filterspecs]\n", cmd);
+    fprintf(stderr, R"init(
+General options:
+  -b, --buffer=<buffer>       Request alternate ring buffer(s):
+                                main system radio events crash default all
+                              Additionally, 'kernel' for userdebug and eng builds, and
+                              'security' for Device Owner installations.
+                              Multiple -b parameters or comma separated list of buffers are
+                              allowed. Buffers are interleaved.
+                              Default -b main,system,crash,kernel.
+  -L, --last                  Dump logs from prior to last reboot from pstore.
+  -c, --clear                 Clear (flush) the entire log and exit.
+                              if -f is specified, clear the specified file and its related rotated
+                              log files instead.
+                              if -L is specified, clear pstore log instead.
+  -d                          Dump the log and then exit (don't block).
+  --pid=<pid>                 Only print logs from the given pid.
+  --wrap                      Sleep for 2 hours or when buffer about to wrap whichever
+                              comes first. Improves efficiency of polling by providing
+                              an about-to-wrap wakeup.
 
-    fprintf(context->error, "options include:\n"
-                    "  -s              Set default filter to silent. Equivalent to filterspec '*:S'\n"
-                    "  -f <file>, --file=<file>               Log to file. Default is stdout\n"
-                    "  -r <kbytes>, --rotate-kbytes=<kbytes>\n"
-                    "                  Rotate log every kbytes. Requires -f option\n"
-                    "  -n <count>, --rotate-count=<count>\n"
-                    "                  Sets max number of rotated logs to <count>, default 4\n"
-                    "  --id=<id>       If the signature id for logging to file changes, then clear\n"
-                    "                  the fileset and continue\n"
-                    "  -v <format>, --format=<format>\n"
-                    "                  Sets log print format verb and adverbs, where <format> is:\n"
-                    "                    brief help long process raw tag thread threadtime time\n"
-                    "                  and individually flagged modifying adverbs can be added:\n"
-                    "                    color descriptive epoch monotonic printable uid\n"
-                    "                    usec UTC year zone\n"
-                    "                  Multiple -v parameters or comma separated list of format and\n"
-                    "                  format modifiers are allowed.\n"
-                    // private and undocumented nsec, no signal, too much noise
-                    // useful for -T or -t <timestamp> accurate testing though.
-                    "  -D, --dividers  Print dividers between each log buffer\n"
-                    "  -c, --clear     Clear (flush) the entire log and exit\n"
-                    "                  if Log to File specified, clear fileset instead\n"
-                    "  -d              Dump the log and then exit (don't block)\n"
-                    "  -e <expr>, --regex=<expr>\n"
-                    "                  Only print lines where the log message matches <expr>\n"
-                    "                  where <expr> is a Perl-compatible regular expression\n"
-                    // Leave --head undocumented as alias for -m
-                    "  -m <count>, --max-count=<count>\n"
-                    "                  Quit after printing <count> lines. This is meant to be\n"
-                    "                  paired with --regex, but will work on its own.\n"
-                    "  --print         Paired with --regex and --max-count to let content bypass\n"
-                    "                  regex filter but still stop at number of matches.\n"
-                    // Leave --tail undocumented as alias for -t
-                    "  -t <count>      Print only the most recent <count> lines (implies -d)\n"
-                    "  -t '<time>'     Print most recent lines since specified time (implies -d)\n"
-                    "  -T <count>      Print only the most recent <count> lines (does not imply -d)\n"
-                    "  -T '<time>'     Print most recent lines since specified time (not imply -d)\n"
-                    "                  count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
-                    "                  'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n"
-                    "  -g, --buffer-size                      Get the size of the ring buffer.\n"
-                    "  -G <size>, --buffer-size=<size>\n"
-                    "                  Set size of log ring buffer, may suffix with K or M.\n"
-                    "  -L, --last      Dump logs from prior to last reboot\n"
-                    "  -b <buffer>, --buffer=<buffer>         Request alternate ring buffer, 'main',\n"
-                    "                  'system', 'radio', 'events', 'crash', 'default' or 'all'.\n"
-                    "                  Additionally, 'kernel' for userdebug and eng builds, and\n"
-                    "                  'security' for Device Owner installations.\n"
-                    "                  Multiple -b parameters or comma separated list of buffers are\n"
-                    "                  allowed. Buffers interleaved. Default -b main,system,crash.\n"
-                    "  -B, --binary    Output the log in binary.\n"
-                    "  -S, --statistics                       Output statistics.\n"
-                    "  -p, --prune     Print prune white and ~black list. Service is specified as\n"
-                    "                  UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n"
-                    "                  with ~, otherwise weighed for longevity if unadorned. All\n"
-                    "                  other pruning activity is oldest first. Special case ~!\n"
-                    "                  represents an automatic quicker pruning for the noisiest\n"
-                    "                  UID as determined by the current statistics.\n"
-                    "  -P '<list> ...', --prune='<list> ...'\n"
-                    "                  Set prune white and ~black list, using same format as\n"
-                    "                  listed above. Must be quoted.\n"
-                    "  --pid=<pid>     Only prints logs from the given pid.\n"
-                    // Check ANDROID_LOG_WRAP_DEFAULT_TIMEOUT value for match to 2 hours
-                    "  --wrap          Sleep for 2 hours or when buffer about to wrap whichever\n"
-                    "                  comes first. Improves efficiency of polling by providing\n"
-                    "                  an about-to-wrap wakeup.\n");
+Formatting:
+  -v, --format=<format>       Sets log print format verb and adverbs, where <format> is one of:
+                                brief help long process raw tag thread threadtime time
+                              Modifying adverbs can be added:
+                                color descriptive epoch monotonic printable uid usec UTC year zone
+                              Multiple -v parameters or comma separated list of format and format
+                              modifiers are allowed.
+  -D, --dividers              Print dividers between each log buffer.
+  -B, --binary                Output the log in binary.
 
-    fprintf(context->error, "\nfilterspecs are a series of \n"
+Outfile files:
+  -f, --file=<file>           Log to file instead of stdout.
+  -r, --rotate-kbytes=<n>     Rotate log every <n> kbytes. Requires -f option.
+  -n, --rotate-count=<count>  Sets max number of rotated logs to <count>, default 4.
+  --id=<id>                   If the signature <id> for logging to file changes, then clear the
+                              associated files and continue.
+
+Logd control:
+ These options send a control message to the logd daemon on device, print its return message if
+ applicable, then exit. They are incompatible with -L, as these attributes do not apply to pstore.
+  -g, --buffer-size           Get the size of the ring buffers within logd.
+  -G, --buffer-size=<size>    Set size of a ring buffer in logd. May suffix with K or M.
+                              This can individually control each buffer's size with -b.
+  -S, --statistics            Output statistics.
+                              --pid can be used to provide pid specific stats.
+  -p, --prune                 Print prune white and ~black list. Service is specified as UID,
+                              UID/PID or /PID. Weighed for quicker pruning if prefix with ~,
+                              otherwise weighed for longevity if unadorned. All other pruning
+                              activity is oldest first. Special case ~! represents an automatic
+                              quicker pruning for the noisiest UID as determined by the current
+                              statistics.
+  -P, --prune='<list> ...'    Set prune white and ~black list, using same format as listed above.
+                              Must be quoted.
+
+Filtering:
+  -s                          Set default filter to silent. Equivalent to filterspec '*:S'
+  -e, --regex=<expr>          Only print lines where the log message matches <expr> where <expr> is
+                              an ECMAScript regular expression.
+  -m, --max-count=<count>     Quit after printing <count> lines. This is meant to be paired with
+                              --regex, but will work on its own.
+  --print                     This option is only applicable when --regex is set and only useful if
+                              --max-count is also provided.
+                              With --print, logcat will print all messages even if they do not
+                              match the regex. Logcat will quit after printing the max-count number
+                              of lines that match the regex.
+  -t <count>                  Print only the most recent <count> lines (implies -d).
+  -t '<time>'                 Print the lines since specified time (implies -d).
+  -T <count>                  Print only the most recent <count> lines (does not imply -d).
+  -T '<time>'                 Print the lines since specified time (not imply -d).
+                              count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'
+                              'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format.
+)init");
+
+    fprintf(stderr, "\nfilterspecs are a series of \n"
                    "  <tag>[:priority]\n\n"
                    "where <tag> is a log component tag (or * for all) and priority is:\n"
                    "  V    Verbose (default for <tag>)\n"
@@ -519,9 +363,8 @@
                    "or defaults to \"threadtime\"\n\n");
 }
 
-static void show_format_help(android_logcat_context_internal* context) {
-    if (!context->error) return;
-    fprintf(context->error,
+static void show_format_help() {
+    fprintf(stderr,
         "-v <format>, --format=<format> options:\n"
         "  Sets log print format verb and adverbs, where <format> is:\n"
         "    brief long process raw tag thread threadtime time\n"
@@ -555,16 +398,13 @@
 }
 // clang-format on
 
-static int setLogFormat(android_logcat_context_internal* context,
-                        const char* formatString) {
-    AndroidLogPrintFormat format;
-
-    format = android_log_formatFromString(formatString);
+int Logcat::SetLogFormat(const char* format_string) {
+    AndroidLogPrintFormat format = android_log_formatFromString(format_string);
 
     // invalid string?
     if (format == FORMAT_OFF) return -1;
 
-    return android_log_setPrintFormat(context->logformat, format);
+    return android_log_setPrintFormat(logformat_.get(), format);
 }
 
 static std::pair<unsigned long, const char*> format_of_size(unsigned long value) {
@@ -577,51 +417,6 @@
     return std::make_pair(value, multipliers[i]);
 }
 
-// String to unsigned int, returns -1 if it fails
-static bool getSizeTArg(const char* ptr, size_t* val, size_t min = 0,
-                        size_t max = SIZE_MAX) {
-    if (!ptr) return false;
-
-    char* endp;
-    errno = 0;
-    size_t ret = (size_t)strtoll(ptr, &endp, 0);
-
-    if (endp[0] || errno) return false;
-
-    if ((ret > max) || (ret < min)) return false;
-
-    *val = ret;
-    return true;
-}
-
-static void logcat_panic(android_logcat_context_internal* context,
-                         enum helpType showHelp, const char* fmt, ...) {
-    context->retval = EXIT_FAILURE;
-    if (!context->error) {
-        context->stop = true;
-        return;
-    }
-
-    va_list args;
-    va_start(args, fmt);
-    vfprintf(context->error, fmt, args);
-    va_end(args);
-
-    switch (showHelp) {
-        case HELP_TRUE:
-            show_help(context);
-            break;
-        case HELP_FORMAT:
-            show_format_help(context);
-            break;
-        case HELP_FALSE:
-        default:
-            break;
-    }
-
-    context->stop = true;
-}
-
 static char* parseTime(log_time& t, const char* cp) {
     char* ep = t.strptime(cp, "%m-%d %H:%M:%S.%q");
     if (ep) return ep;
@@ -699,32 +494,18 @@
     return retval;
 }
 
-const char* getenv(android_logcat_context_internal* context, const char* name) {
-    if (!context->envp || !name || !*name) return nullptr;
-
-    for (size_t len = strlen(name), i = 0; context->envp[i]; ++i) {
-        if (strncmp(context->envp[i], name, len)) continue;
-        if (context->envp[i][len] == '=') return &context->envp[i][len + 1];
-    }
-    return nullptr;
-}
-
-}  // namespace android
-
-void reportErrorName(const char** current, const char* name,
-                     bool blockSecurity) {
-    if (*current) return;
-    if (!blockSecurity || (android_name_to_log_id(name) != LOG_ID_SECURITY)) {
-        *current = name;
+void ReportErrorName(const std::string& name, bool allow_security,
+                     std::vector<std::string>* errors) {
+    if (allow_security || name != "security") {
+        errors->emplace_back(name);
     }
 }
 
-static int __logcat(android_logcat_context_internal* context) {
-    using namespace android;
-    int err;
+int Logcat::Run(int argc, char** argv) {
     bool hasSetLogFormat = false;
     bool clearLog = false;
-    bool allSelected = false;
+    bool security_buffer_selected =
+            false;  // Do not report errors on the security buffer unless it is explicitly named.
     bool getLogSize = false;
     bool getPruneList = false;
     bool printStatistics = false;
@@ -734,114 +515,15 @@
     const char* setId = nullptr;
     int mode = ANDROID_LOG_RDONLY;
     std::string forceFilters;
-    log_device_t* dev;
-    struct logger_list* logger_list;
     size_t tail_lines = 0;
     log_time tail_time(log_time::EPOCH);
     size_t pid = 0;
     bool got_t = false;
-
-    // object instantiations before goto's can happen
-    log_device_t unexpected("unexpected", false);
-    const char* openDeviceFail = nullptr;
-    const char* clearFail = nullptr;
-    const char* setSizeFail = nullptr;
-    const char* getSizeFail = nullptr;
-    int argc = context->argc;
-    char* const* argv = context->argv;
-
-    context->output = stdout;
-    context->error = stderr;
-
-    for (int i = 0; i < argc; ++i) {
-        // Simulate shell stderr redirect parsing
-        if ((argv[i][0] != '2') || (argv[i][1] != '>')) continue;
-
-        // Append to file not implemented, just open file
-        size_t skip = (argv[i][2] == '>') + 2;
-        if (!strcmp(&argv[i][skip], "/dev/null")) {
-            context->stderr_null = true;
-        } else if (!strcmp(&argv[i][skip], "&1")) {
-            context->stderr_stdout = true;
-        } else {
-            // stderr file redirections are not supported
-            fprintf(context->stderr_stdout ? stdout : stderr,
-                    "stderr redirection to file %s unsupported, skipping\n",
-                    &argv[i][skip]);
-        }
-        // Only the first one
-        break;
-    }
-
-    const char* filename = nullptr;
-    for (int i = 0; i < argc; ++i) {
-        // Simulate shell stdout redirect parsing
-        if (argv[i][0] != '>') continue;
-
-        // Append to file not implemented, just open file
-        filename = &argv[i][(argv[i][1] == '>') + 1];
-        // Only the first one
-        break;
-    }
-
-    // Deal with setting up file descriptors and FILE pointers
-    if (context->error_fd >= 0) {  // Is an error file descriptor supplied?
-        if (context->error_fd == context->output_fd) {
-            context->stderr_stdout = true;
-        } else if (context->stderr_null) {  // redirection told us to close it
-            close(context->error_fd);
-            context->error_fd = -1;
-        } else {  // All Ok, convert error to a FILE pointer
-            context->error = fdopen(context->error_fd, "web");
-            if (!context->error) {
-                context->retval = -errno;
-                fprintf(context->stderr_stdout ? stdout : stderr,
-                        "Failed to fdopen(error_fd=%d) %s\n", context->error_fd,
-                        strerror(errno));
-                goto exit;
-            }
-        }
-    }
-    if (context->output_fd >= 0) {  // Is an output file descriptor supplied?
-        if (filename) {  // redirect to file, close supplied file descriptor.
-            close(context->output_fd);
-            context->output_fd = -1;
-        } else {  // All Ok, convert output to a FILE pointer
-            context->output = fdopen(context->output_fd, "web");
-            if (!context->output) {
-                context->retval = -errno;
-                fprintf(context->stderr_stdout ? stdout : context->error,
-                        "Failed to fdopen(output_fd=%d) %s\n",
-                        context->output_fd, strerror(errno));
-                goto exit;
-            }
-        }
-    }
-    if (filename) {  // We supplied an output file redirected in command line
-        context->output = fopen(filename, "web");
-    }
-    // Deal with 2>&1
-    if (context->stderr_stdout) context->error = context->output;
-    // Deal with 2>/dev/null
-    if (context->stderr_null) {
-        context->error_fd = -1;
-        context->error = nullptr;
-    }
-    // Only happens if output=stdout or output=filename
-    if ((context->output_fd < 0) && context->output) {
-        context->output_fd = fileno(context->output);
-    }
-    // Only happens if error=stdout || error=stderr
-    if ((context->error_fd < 0) && context->error) {
-        context->error_fd = fileno(context->error);
-    }
-
-    context->logformat = android_log_format_new();
+    unsigned id_mask = 0;
 
     if (argc == 2 && !strcmp(argv[1], "--help")) {
-        show_help(context);
-        context->retval = EXIT_SUCCESS;
-        goto exit;
+        show_help();
+        return EXIT_SUCCESS;
     }
 
     // meant to catch comma-delimited values, but cast a wider
@@ -898,11 +580,13 @@
             case 0:
                 // only long options
                 if (long_options[option_index].name == pid_str) {
-                    // ToDo: determine runtime PID_MAX?
-                    if (!getSizeTArg(optarg, &pid, 1)) {
-                        logcat_panic(context, HELP_TRUE, "%s %s out of range\n",
-                                     long_options[option_index].name, optarg);
-                        goto exit;
+                    if (pid != 0) {
+                        error(EXIT_FAILURE, 0, "Only one --pid argument can be provided.");
+                    }
+
+                    if (!ParseUint(optarg, &pid) || pid < 1) {
+                        error(EXIT_FAILURE, 0, "%s %s out of range.",
+                              long_options[option_index].name, optarg);
                     }
                     break;
                 }
@@ -911,26 +595,23 @@
                             ANDROID_LOG_NONBLOCK;
                     // ToDo: implement API that supports setting a wrap timeout
                     size_t dummy = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
-                    if (optarg && !getSizeTArg(optarg, &dummy, 1)) {
-                        logcat_panic(context, HELP_TRUE, "%s %s out of range\n",
-                                     long_options[option_index].name, optarg);
-                        goto exit;
+                    if (optarg && (!ParseUint(optarg, &dummy) || dummy < 1)) {
+                        error(EXIT_FAILURE, 0, "%s %s out of range.",
+                              long_options[option_index].name, optarg);
                     }
-                    if ((dummy != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) &&
-                        context->error) {
-                        fprintf(context->error,
-                                "WARNING: %s %u seconds, ignoring %zu\n",
-                                long_options[option_index].name,
-                                ANDROID_LOG_WRAP_DEFAULT_TIMEOUT, dummy);
+                    if (dummy != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) {
+                        fprintf(stderr, "WARNING: %s %u seconds, ignoring %zu\n",
+                                long_options[option_index].name, ANDROID_LOG_WRAP_DEFAULT_TIMEOUT,
+                                dummy);
                     }
                     break;
                 }
                 if (long_options[option_index].name == print_str) {
-                    context->printItAnyways = true;
+                    print_it_anyways_ = true;
                     break;
                 }
                 if (long_options[option_index].name == debug_str) {
-                    context->debug = true;
+                    debug_ = true;
                     break;
                 }
                 if (long_options[option_index].name == id_str) {
@@ -940,7 +621,7 @@
 
             case 's':
                 // default to all silent
-                android_log_addFilterRule(context->logformat, "*:s");
+                android_log_addFilterRule(logformat_.get(), "*:s");
                 break;
 
             case 'c':
@@ -965,25 +646,18 @@
                 if (strspn(optarg, "0123456789") != strlen(optarg)) {
                     char* cp = parseTime(tail_time, optarg);
                     if (!cp) {
-                        logcat_panic(context, HELP_FALSE, "-%c \"%s\" not in time format\n", c,
-                                     optarg);
-                        goto exit;
+                        error(EXIT_FAILURE, 0, "-%c '%s' not in time format.", c, optarg);
                     }
                     if (*cp) {
                         char ch = *cp;
                         *cp = '\0';
-                        if (context->error) {
-                            fprintf(context->error, "WARNING: -%c \"%s\"\"%c%s\" time truncated\n",
-                                    c, optarg, ch, cp + 1);
-                        }
+                        fprintf(stderr, "WARNING: -%c '%s' '%c%s' time truncated\n", c, optarg, ch,
+                                cp + 1);
                         *cp = ch;
                     }
                 } else {
-                    if (!getSizeTArg(optarg, &tail_lines, 1)) {
-                        if (context->error) {
-                            fprintf(context->error, "WARNING: -%c %s invalid, setting to 1\n", c,
-                                    optarg);
-                        }
+                    if (!ParseUint(optarg, &tail_lines) || tail_lines < 1) {
+                        fprintf(stderr, "WARNING: -%c %s invalid, setting to 1\n", c, optarg);
                         tail_lines = 1;
                     }
                 }
@@ -994,14 +668,13 @@
                 break;
 
             case 'e':
-                context->regex = new pcrecpp::RE(optarg);
+                regex_.reset(new std::regex(optarg));
                 break;
 
             case 'm': {
-                if (!getSizeTArg(optarg, &context->maxCount)) {
-                    logcat_panic(context, HELP_FALSE,
-                                 "-%c \"%s\" isn't an integer greater than zero\n", c, optarg);
-                    goto exit;
+                if (!ParseUint(optarg, &max_count_) || max_count_ < 1) {
+                    error(EXIT_FAILURE, 0, "-%c '%s' isn't an integer greater than zero.", c,
+                          optarg);
                 }
             } break;
 
@@ -1013,37 +686,8 @@
                 FALLTHROUGH_INTENDED;
 
             case 'G': {
-                char* cp;
-                if (strtoll(optarg, &cp, 0) > 0) {
-                    setLogSize = strtoll(optarg, &cp, 0);
-                } else {
-                    setLogSize = 0;
-                }
-
-                switch (*cp) {
-                    case 'g':
-                    case 'G':
-                        setLogSize *= 1024;
-                        FALLTHROUGH_INTENDED;
-                    case 'm':
-                    case 'M':
-                        setLogSize *= 1024;
-                        FALLTHROUGH_INTENDED;
-                    case 'k':
-                    case 'K':
-                        setLogSize *= 1024;
-                        FALLTHROUGH_INTENDED;
-                    case '\0':
-                        break;
-
-                    default:
-                        setLogSize = 0;
-                }
-
-                if (!setLogSize) {
-                    logcat_panic(context, HELP_FALSE,
-                                 "ERROR: -G <num><multiplier>\n");
-                    goto exit;
+                if (!ParseByteCount(optarg, &setLogSize) || setLogSize < 1) {
+                    error(EXIT_FAILURE, 0, "-G must be specified as <num><multiplier>.");
                 }
             } break;
 
@@ -1058,67 +702,28 @@
                 setPruneList = optarg;
                 break;
 
-            case 'b': {
-                std::unique_ptr<char, void (*)(void*)> buffers(strdup(optarg), free);
-                char* arg = buffers.get();
-                unsigned idMask = 0;
-                char* sv = nullptr;  // protect against -ENOMEM above
-                while (!!(arg = strtok_r(arg, delimiters, &sv))) {
-                    if (!strcmp(arg, "default")) {
-                        idMask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) |
-                                  (1 << LOG_ID_CRASH);
-                    } else if (!strcmp(arg, "all")) {
-                        allSelected = true;
-                        idMask = (unsigned)-1;
+            case 'b':
+                for (const auto& buffer : Split(optarg, delimiters)) {
+                    if (buffer == "default") {
+                        id_mask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) | (1 << LOG_ID_CRASH);
+                    } else if (buffer == "all") {
+                        id_mask = -1;
                     } else {
-                        log_id_t log_id = android_name_to_log_id(arg);
-                        const char* name = android_log_id_to_name(log_id);
-
-                        if (!!strcmp(name, arg)) {
-                            logcat_panic(context, HELP_TRUE,
-                                         "unknown buffer %s\n", arg);
-                            goto exit;
+                        log_id_t log_id = android_name_to_log_id(buffer.c_str());
+                        if (log_id >= LOG_ID_MAX) {
+                            error(EXIT_FAILURE, 0, "Unknown buffer '%s' listed for -b.",
+                                  buffer.c_str());
                         }
-                        if (log_id == LOG_ID_SECURITY) allSelected = false;
-                        idMask |= (1 << log_id);
-                    }
-                    arg = nullptr;
-                }
-
-                for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
-                    const char* name = android_log_id_to_name((log_id_t)i);
-                    log_id_t log_id = android_name_to_log_id(name);
-
-                    if (log_id != (log_id_t)i) continue;
-                    if (!(idMask & (1 << i))) continue;
-
-                    bool found = false;
-                    for (dev = context->devices; dev; dev = dev->next) {
-                        if (!strcmp(name, dev->device)) {
-                            found = true;
-                            break;
+                        if (log_id == LOG_ID_SECURITY) {
+                            security_buffer_selected = true;
                         }
-                        if (!dev->next) break;
+                        id_mask |= (1 << log_id);
                     }
-                    if (found) continue;
-
-                    bool binary = !strcmp(name, "events") ||
-                                  !strcmp(name, "security") ||
-                                  !strcmp(name, "stats");
-                    log_device_t* d = new log_device_t(name, binary);
-
-                    if (dev) {
-                        dev->next = d;
-                        dev = d;
-                    } else {
-                        context->devices = dev = d;
-                    }
-                    context->devCount++;
                 }
-            } break;
+                break;
 
             case 'B':
-                context->printBinary = 1;
+                print_binary_ = 1;
                 break;
 
             case 'f':
@@ -1126,43 +731,34 @@
                     tail_time = lastLogTime(optarg);
                 }
                 // redirect output to a file
-                context->outputFileName = optarg;
+                output_file_name_ = optarg;
                 break;
 
             case 'r':
-                if (!getSizeTArg(optarg, &context->logRotateSizeKBytes, 1)) {
-                    logcat_panic(context, HELP_TRUE, "Invalid parameter \"%s\" to -r\n", optarg);
-                    goto exit;
+                if (!ParseUint(optarg, &log_rotate_size_kb_) || log_rotate_size_kb_ < 1) {
+                    error(EXIT_FAILURE, 0, "Invalid parameter '%s' to -r.", optarg);
                 }
                 break;
 
             case 'n':
-                if (!getSizeTArg(optarg, &context->maxRotatedLogs, 1)) {
-                    logcat_panic(context, HELP_TRUE, "Invalid parameter \"%s\" to -n\n", optarg);
-                    goto exit;
+                if (!ParseUint(optarg, &max_rotated_logs_) || max_rotated_logs_ < 1) {
+                    error(EXIT_FAILURE, 0, "Invalid parameter '%s' to -n.", optarg);
                 }
                 break;
 
-            case 'v': {
+            case 'v':
                 if (!strcmp(optarg, "help") || !strcmp(optarg, "--help")) {
-                    show_format_help(context);
-                    context->retval = EXIT_SUCCESS;
-                    goto exit;
+                    show_format_help();
+                    return EXIT_SUCCESS;
                 }
-                std::unique_ptr<char, void (*)(void*)> formats(strdup(optarg), free);
-                char* arg = formats.get();
-                char* sv = nullptr;  // protect against -ENOMEM above
-                while (!!(arg = strtok_r(arg, delimiters, &sv))) {
-                    err = setLogFormat(context, arg);
+                for (const auto& arg : Split(optarg, delimiters)) {
+                    int err = SetLogFormat(arg.c_str());
                     if (err < 0) {
-                        logcat_panic(context, HELP_FORMAT,
-                                     "Invalid parameter \"%s\" to -v\n", arg);
-                        goto exit;
+                        error(EXIT_FAILURE, 0, "Invalid parameter '%s' to -v.", arg.c_str());
                     }
-                    arg = nullptr;
                     if (err) hasSetLogFormat = true;
                 }
-            } break;
+                break;
 
             case 'Q':
 #define LOGCAT_FILTER "androidboot.logcat="
@@ -1180,8 +776,7 @@
                 {
                     // if not in emulator, exit quietly
                     if (false == android::base::GetBoolProperty(QEMU_PROPERTY, false)) {
-                        context->retval = EXIT_SUCCESS;
-                        goto exit;
+                        return EXIT_SUCCESS;
                     }
 
                     std::string cmdline = android::base::GetProperty(QEMU_CMDLINE, "");
@@ -1192,8 +787,7 @@
                     const char* logcatFilter = strstr(cmdline.c_str(), LOGCAT_FILTER);
                     // if nothing found or invalid filters, exit quietly
                     if (!logcatFilter) {
-                        context->retval = EXIT_SUCCESS;
-                        goto exit;
+                        return EXIT_SUCCESS;
                     }
 
                     const char* p = logcatFilter + strlen(LOGCAT_FILTER);
@@ -1212,8 +806,7 @@
                     } else if (console) {
                         p = console + strlen(CONSOLE_OPTION);
                     } else {
-                        context->retval = EXIT_FAILURE;
-                        goto exit;
+                        return EXIT_FAILURE;
                     }
 
                     q = strpbrk(p, " \t\n\r");
@@ -1230,37 +823,26 @@
                             devname = devname.substr(0, pos);
                         }
                     }
-                    cmdline.erase();
 
-                    if (context->error) {
-                        fprintf(context->error, "logcat using %s\n",
-                                devname.c_str());
+                    fprintf(stderr, "logcat using %s\n", devname.c_str());
+
+                    int fd = open(devname.c_str(), O_WRONLY | O_CLOEXEC);
+                    if (fd < 0) {
+                        break;
                     }
 
-                    FILE* fp = fopen(devname.c_str(), "web");
-                    devname.erase();
-                    if (!fp) break;
-
                     if (consolePipe) {
                         // need the trailing '\0'
-                        if(!android::base::WriteFully(fileno(fp), pipePurpose.c_str(),
-                                    pipePurpose.size() + 1)) {
-                            fclose(fp);
-                            context->retval = EXIT_FAILURE;
-                            goto exit;
+                        if (!android::base::WriteFully(fd, pipePurpose.c_str(),
+                                                       pipePurpose.size() + 1)) {
+                            close(fd);
+                            return EXIT_FAILURE;
                         }
                     }
-
                     // close output and error channels, replace with console
-                    android::close_output(context);
-                    android::close_error(context);
-                    context->stderr_stdout = true;
-                    context->output = fp;
-                    context->output_fd = fileno(fp);
-                    if (context->stderr_null) break;
-                    context->stderr_stdout = true;
-                    context->error = fp;
-                    context->error_fd = fileno(fp);
+                    dup2(fd, output_fd_.get());
+                    dup2(fd, STDERR_FILENO);
+                    close(fd);
                 }
                 break;
 
@@ -1269,65 +851,53 @@
                 break;
 
             case ':':
-                logcat_panic(context, HELP_TRUE, "Option -%c needs an argument\n", optopt);
-                goto exit;
+                error(EXIT_FAILURE, 0, "Option '%s' needs an argument.", argv[optind - 1]);
+                break;
 
             case 'h':
-                show_help(context);
-                show_format_help(context);
-                goto exit;
+                show_help();
+                show_format_help();
+                return EXIT_SUCCESS;
+
+            case '?':
+                error(EXIT_FAILURE, 0, "Unknown option '%s'.", argv[optind - 1]);
+                break;
 
             default:
-                logcat_panic(context, HELP_TRUE, "Unrecognized Option %c\n", optopt);
-                goto exit;
+                error(EXIT_FAILURE, 0, "Unknown getopt_long() result '%c'.", c);
         }
     }
 
-    if (context->maxCount && got_t) {
-        logcat_panic(context, HELP_TRUE,
-                     "Cannot use -m (--max-count) and -t together\n");
-        goto exit;
+    if (max_count_ && got_t) {
+        error(EXIT_FAILURE, 0, "Cannot use -m (--max-count) and -t together.");
     }
-    if (context->printItAnyways && (!context->regex || !context->maxCount)) {
+    if (print_it_anyways_ && (!regex_ || !max_count_)) {
         // One day it would be nice if --print -v color and --regex <expr>
         // could play with each other and show regex highlighted content.
-        // clang-format off
-        if (context->error) {
-            fprintf(context->error, "WARNING: "
-                            "--print ignored, to be used in combination with\n"
-                                "         "
-                            "--regex <expr> and --max-count <N>\n");
-        }
-        context->printItAnyways = false;
+        fprintf(stderr,
+                "WARNING: "
+                "--print ignored, to be used in combination with\n"
+                "         "
+                "--regex <expr> and --max-count <N>\n");
+        print_it_anyways_ = false;
     }
 
-    if (!context->devices) {
-        dev = context->devices = new log_device_t("main", false);
-        context->devCount = 1;
-        if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
-            dev = dev->next = new log_device_t("system", false);
-            context->devCount++;
-        }
-        if (android_name_to_log_id("crash") == LOG_ID_CRASH) {
-            dev = dev->next = new log_device_t("crash", false);
-            context->devCount++;
-        }
+    // If no buffers are specified, default to using these buffers.
+    if (id_mask == 0) {
+        id_mask = (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) | (1 << LOG_ID_CRASH) |
+                  (1 << LOG_ID_KERNEL);
     }
 
-    if (!!context->logRotateSizeKBytes && !context->outputFileName) {
-        logcat_panic(context, HELP_TRUE, "-r requires -f as well\n");
-        goto exit;
+    if (log_rotate_size_kb_ != 0 && !output_file_name_) {
+        error(EXIT_FAILURE, 0, "-r requires -f as well.");
     }
 
-    if (!!setId) {
-        if (!context->outputFileName) {
-            logcat_panic(context, HELP_TRUE,
-                         "--id='%s' requires -f as well\n", setId);
-            goto exit;
+    if (setId != 0) {
+        if (!output_file_name_) {
+            error(EXIT_FAILURE, 0, "--id='%s' requires -f as well.", setId);
         }
 
-        std::string file_name = android::base::StringPrintf(
-                                        "%s.id", context->outputFileName);
+        std::string file_name = StringPrintf("%s.id", output_file_name_);
         std::string file;
         bool file_ok = android::base::ReadFileToString(file_name, &file);
         android::base::WriteStringToFile(setId, file_name, S_IRUSR | S_IWUSR,
@@ -1336,398 +906,264 @@
     }
 
     if (!hasSetLogFormat) {
-        const char* logFormat = android::getenv(context, "ANDROID_PRINTF_LOG");
+        const char* logFormat = getenv("ANDROID_PRINTF_LOG");
 
         if (!!logFormat) {
-            std::unique_ptr<char, void (*)(void*)> formats(strdup(logFormat),
-                                                           free);
-            char* sv = nullptr;  // protect against -ENOMEM above
-            char* arg = formats.get();
-            while (!!(arg = strtok_r(arg, delimiters, &sv))) {
-                err = setLogFormat(context, arg);
+            for (const auto& arg : Split(logFormat, delimiters)) {
+                int err = SetLogFormat(arg.c_str());
                 // environment should not cause crash of logcat
-                if ((err < 0) && context->error) {
-                    fprintf(context->error,
-                            "invalid format in ANDROID_PRINTF_LOG '%s'\n", arg);
+                if (err < 0) {
+                    fprintf(stderr, "invalid format in ANDROID_PRINTF_LOG '%s'\n", arg.c_str());
                 }
-                arg = nullptr;
                 if (err > 0) hasSetLogFormat = true;
             }
         }
         if (!hasSetLogFormat) {
-            setLogFormat(context, "threadtime");
+            SetLogFormat("threadtime");
         }
     }
 
     if (forceFilters.size()) {
-        err = android_log_addFilterString(context->logformat,
-                                          forceFilters.c_str());
+        int err = android_log_addFilterString(logformat_.get(), forceFilters.c_str());
         if (err < 0) {
-            logcat_panic(context, HELP_FALSE,
-                         "Invalid filter expression in logcat args\n");
-            goto exit;
+            error(EXIT_FAILURE, 0, "Invalid filter expression in logcat args.");
         }
     } else if (argc == optind) {
         // Add from environment variable
-        const char* env_tags_orig = android::getenv(context, "ANDROID_LOG_TAGS");
+        const char* env_tags_orig = getenv("ANDROID_LOG_TAGS");
 
         if (!!env_tags_orig) {
-            err = android_log_addFilterString(context->logformat,
-                                              env_tags_orig);
+            int err = android_log_addFilterString(logformat_.get(), env_tags_orig);
 
             if (err < 0) {
-                logcat_panic(context, HELP_TRUE,
-                            "Invalid filter expression in ANDROID_LOG_TAGS\n");
-                goto exit;
+                error(EXIT_FAILURE, 0, "Invalid filter expression in ANDROID_LOG_TAGS.");
             }
         }
     } else {
         // Add from commandline
         for (int i = optind ; i < argc ; i++) {
-            // skip stderr redirections of _all_ kinds
-            if ((argv[i][0] == '2') && (argv[i][1] == '>')) continue;
-            // skip stdout redirections of _all_ kinds
-            if (argv[i][0] == '>') continue;
-
-            err = android_log_addFilterString(context->logformat, argv[i]);
+            int err = android_log_addFilterString(logformat_.get(), argv[i]);
             if (err < 0) {
-                logcat_panic(context, HELP_TRUE,
-                             "Invalid filter expression '%s'\n", argv[i]);
-                goto exit;
+                error(EXIT_FAILURE, 0, "Invalid filter expression '%s'.", argv[i]);
             }
         }
     }
 
-    dev = context->devices;
-    if (tail_time != log_time::EPOCH) {
-        logger_list = android_logger_list_alloc_time(mode, tail_time, pid);
-    } else {
-        logger_list = android_logger_list_alloc(mode, tail_lines, pid);
+    if (mode & ANDROID_LOG_PSTORE) {
+        if (output_file_name_) {
+            error(EXIT_FAILURE, 0, "-c is ambiguous with both -f and -L specified.");
+        }
+        if (setLogSize || getLogSize || printStatistics || getPruneList || setPruneList) {
+            error(EXIT_FAILURE, 0, "-L is incompatible with -g/-G, -S, and -p/-P.");
+        }
+        if (clearLog) {
+            unlink("/sys/fs/pstore/pmsg-ramoops-0");
+            return EXIT_SUCCESS;
+        }
     }
-    // We have three orthogonal actions below to clear, set log size and
-    // get log size. All sharing the same iteration loop.
-    while (dev) {
-        dev->logger_list = logger_list;
-        dev->logger = android_logger_open(logger_list,
-                                          android_name_to_log_id(dev->device));
-        if (!dev->logger) {
-            reportErrorName(&openDeviceFail, dev->device, allSelected);
-            dev = dev->next;
-            continue;
+
+    if (output_file_name_) {
+        if (setLogSize || getLogSize || printStatistics || getPruneList || setPruneList) {
+            error(EXIT_FAILURE, 0, "-f is incompatible with -g/-G, -S, and -p/-P.");
         }
 
         if (clearLog || setId) {
-            if (context->outputFileName) {
-                int maxRotationCountDigits =
-                    (context->maxRotatedLogs > 0) ?
-                        (int)(floor(log10(context->maxRotatedLogs) + 1)) :
-                        0;
+            int max_rotation_count_digits =
+                    max_rotated_logs_ > 0 ? (int)(floor(log10(max_rotated_logs_) + 1)) : 0;
 
-                for (int i = context->maxRotatedLogs ; i >= 0 ; --i) {
-                    std::string file;
+            for (int i = max_rotated_logs_; i >= 0; --i) {
+                std::string file;
 
-                    if (!i) {
-                        file = android::base::StringPrintf(
-                            "%s", context->outputFileName);
-                    } else {
-                        file = android::base::StringPrintf("%s.%.*d",
-                            context->outputFileName, maxRotationCountDigits, i);
-                    }
-
-                    if (!file.length()) {
-                        perror("while clearing log files");
-                        reportErrorName(&clearFail, dev->device, allSelected);
-                        break;
-                    }
-
-                    err = unlink(file.c_str());
-
-                    if (err < 0 && errno != ENOENT && !clearFail) {
-                        perror("while clearing log files");
-                        reportErrorName(&clearFail, dev->device, allSelected);
-                    }
+                if (!i) {
+                    file = output_file_name_;
+                } else {
+                    file = StringPrintf("%s.%.*d", output_file_name_, max_rotation_count_digits, i);
                 }
-            } else if (android_logger_clear(dev->logger)) {
-                reportErrorName(&clearFail, dev->device, allSelected);
+
+                int err = unlink(file.c_str());
+
+                if (err < 0 && errno != ENOENT) {
+                    fprintf(stderr, "failed to delete log file '%s': %s\n", file.c_str(),
+                            strerror(errno));
+                }
+            }
+        }
+
+        if (clearLog) {
+            return EXIT_SUCCESS;
+        }
+    }
+
+    std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
+            nullptr, &android_logger_list_free};
+    if (tail_time != log_time::EPOCH) {
+        logger_list.reset(android_logger_list_alloc_time(mode, tail_time, pid));
+    } else {
+        logger_list.reset(android_logger_list_alloc(mode, tail_lines, pid));
+    }
+    // We have three orthogonal actions below to clear, set log size and
+    // get log size. All sharing the same iteration loop.
+    std::vector<std::string> open_device_failures;
+    std::vector<std::string> clear_failures;
+    std::vector<std::string> set_size_failures;
+    std::vector<std::string> get_size_failures;
+
+    for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
+        if (!(id_mask & (1 << i))) continue;
+        const char* buffer_name = android_log_id_to_name(static_cast<log_id_t>(i));
+
+        auto logger = android_logger_open(logger_list.get(), static_cast<log_id_t>(i));
+        if (logger == nullptr) {
+            ReportErrorName(buffer_name, security_buffer_selected, &open_device_failures);
+            continue;
+        }
+
+        if (clearLog) {
+            if (android_logger_clear(logger)) {
+                ReportErrorName(buffer_name, security_buffer_selected, &clear_failures);
             }
         }
 
         if (setLogSize) {
-            if (android_logger_set_log_size(dev->logger, setLogSize)) {
-                reportErrorName(&setSizeFail, dev->device, allSelected);
+            if (android_logger_set_log_size(logger, setLogSize)) {
+                ReportErrorName(buffer_name, security_buffer_selected, &set_size_failures);
             }
         }
 
         if (getLogSize) {
-            long size = android_logger_get_log_size(dev->logger);
-            long readable = android_logger_get_log_readable_size(dev->logger);
+            long size = android_logger_get_log_size(logger);
+            long readable = android_logger_get_log_readable_size(logger);
 
-            if ((size < 0) || (readable < 0)) {
-                reportErrorName(&getSizeFail, dev->device, allSelected);
+            if (size < 0 || readable < 0) {
+                ReportErrorName(buffer_name, security_buffer_selected, &get_size_failures);
             } else {
                 auto size_format = format_of_size(size);
                 auto readable_format = format_of_size(readable);
                 std::string str = android::base::StringPrintf(
-                       "%s: ring buffer is %lu %sB (%lu %sB consumed),"
-                         " max entry is %d B, max payload is %d B\n",
-                       dev->device,
-                       size_format.first, size_format.second,
-                       readable_format.first, readable_format.second,
-                       (int)LOGGER_ENTRY_MAX_LEN,
-                       (int)LOGGER_ENTRY_MAX_PAYLOAD);
-                TEMP_FAILURE_RETRY(write(context->output_fd,
-                                         str.data(), str.length()));
+                        "%s: ring buffer is %lu %sB (%lu %sB consumed),"
+                        " max entry is %d B, max payload is %d B\n",
+                        buffer_name, size_format.first, size_format.second, readable_format.first,
+                        readable_format.second, (int)LOGGER_ENTRY_MAX_LEN,
+                        (int)LOGGER_ENTRY_MAX_PAYLOAD);
+                TEMP_FAILURE_RETRY(write(output_fd_.get(), str.data(), str.length()));
             }
         }
-
-        dev = dev->next;
     }
 
-    context->retval = EXIT_SUCCESS;
-
     // report any errors in the above loop and exit
-    if (openDeviceFail) {
-        logcat_panic(context, HELP_FALSE,
-                     "Unable to open log device '%s'\n", openDeviceFail);
-        goto close;
+    if (!open_device_failures.empty()) {
+        error(EXIT_FAILURE, 0, "Unable to open log device%s '%s'.",
+              open_device_failures.size() > 1 ? "s" : "", Join(open_device_failures, ",").c_str());
     }
-    if (clearFail) {
-        logcat_panic(context, HELP_FALSE,
-                     "failed to clear the '%s' log\n", clearFail);
-        goto close;
+    if (!clear_failures.empty()) {
+        error(EXIT_FAILURE, 0, "failed to clear the '%s' log%s.", Join(clear_failures, ",").c_str(),
+              clear_failures.size() > 1 ? "s" : "");
     }
-    if (setSizeFail) {
-        logcat_panic(context, HELP_FALSE,
-                     "failed to set the '%s' log size\n", setSizeFail);
-        goto close;
+    if (!set_size_failures.empty()) {
+        error(EXIT_FAILURE, 0, "failed to set the '%s' log size%s.",
+              Join(set_size_failures, ",").c_str(), set_size_failures.size() > 1 ? "s" : "");
     }
-    if (getSizeFail) {
-        logcat_panic(context, HELP_FALSE,
-                     "failed to get the readable '%s' log size", getSizeFail);
-        goto close;
+    if (!get_size_failures.empty()) {
+        error(EXIT_FAILURE, 0, "failed to get the readable '%s' log size%s.",
+              Join(get_size_failures, ",").c_str(), get_size_failures.size() > 1 ? "s" : "");
     }
 
     if (setPruneList) {
         size_t len = strlen(setPruneList);
-        // extra 32 bytes are needed by android_logger_set_prune_list
-        size_t bLen = len + 32;
-        char* buf = nullptr;
-        if (asprintf(&buf, "%-*s", (int)(bLen - 1), setPruneList) > 0) {
-            buf[len] = '\0';
-            if (android_logger_set_prune_list(logger_list, buf, bLen)) {
-                logcat_panic(context, HELP_FALSE,
-                             "failed to set the prune list");
-            }
-            free(buf);
-        } else {
-            logcat_panic(context, HELP_FALSE,
-                         "failed to set the prune list (alloc)");
+        if (android_logger_set_prune_list(logger_list.get(), setPruneList, len)) {
+            error(EXIT_FAILURE, 0, "Failed to set the prune list.");
         }
-        goto close;
+        return EXIT_SUCCESS;
     }
 
     if (printStatistics || getPruneList) {
-        size_t len = 8192;
-        char* buf;
+        std::string buf(8192, '\0');
+        size_t ret_length = 0;
+        int retry = 32;
 
-        for (int retry = 32; (retry >= 0) && ((buf = new char[len]));
-             delete[] buf, buf = nullptr, --retry) {
+        for (; retry >= 0; --retry) {
             if (getPruneList) {
-                android_logger_get_prune_list(logger_list, buf, len);
+                android_logger_get_prune_list(logger_list.get(), buf.data(), buf.size());
             } else {
-                android_logger_get_statistics(logger_list, buf, len);
+                android_logger_get_statistics(logger_list.get(), buf.data(), buf.size());
             }
-            buf[len - 1] = '\0';
-            if (atol(buf) < 3) {
-                delete[] buf;
-                buf = nullptr;
+
+            ret_length = atol(buf.c_str());
+            if (ret_length < 3) {
+                error(EXIT_FAILURE, 0, "Failed to read data.");
+            }
+
+            if (ret_length < buf.size()) {
                 break;
             }
-            size_t ret = atol(buf) + 1;
-            if (ret <= len) {
-                len = ret;
-                break;
-            }
-            len = ret;
+
+            buf.resize(ret_length + 1);
         }
 
-        if (!buf) {
-            logcat_panic(context, HELP_FALSE, "failed to read data");
-            goto close;
+        if (retry < 0) {
+            error(EXIT_FAILURE, 0, "Failed to read data.");
         }
 
-        // remove trailing FF
-        char* cp = buf + len - 1;
-        *cp = '\0';
-        bool truncated = *--cp != '\f';
-        if (!truncated) *cp = '\0';
-
-        // squash out the byte count
-        cp = buf;
-        if (!truncated) {
-            while (isdigit(*cp)) ++cp;
-            if (*cp == '\n') ++cp;
+        buf.resize(ret_length);
+        if (buf.back() == '\f') {
+            buf.pop_back();
         }
 
-        len = strlen(cp);
-        TEMP_FAILURE_RETRY(write(context->output_fd, cp, len));
-        delete[] buf;
-        goto close;
+        // Remove the byte count prefix
+        const char* cp = buf.c_str();
+        while (isdigit(*cp)) ++cp;
+        if (*cp == '\n') ++cp;
+
+        size_t len = strlen(cp);
+        TEMP_FAILURE_RETRY(write(output_fd_.get(), cp, len));
+        return EXIT_SUCCESS;
     }
 
-    if (getLogSize || setLogSize || clearLog) goto close;
+    if (getLogSize || setLogSize || clearLog) return EXIT_SUCCESS;
 
-    setupOutputAndSchedulingPolicy(context, !(mode & ANDROID_LOG_NONBLOCK));
-    if (context->stop) goto close;
+    SetupOutputAndSchedulingPolicy(!(mode & ANDROID_LOG_NONBLOCK));
 
-    // LOG_EVENT_INT(10, 12345);
-    // LOG_EVENT_LONG(11, 0x1122334455667788LL);
-    // LOG_EVENT_STRING(0, "whassup, doc?");
-
-    dev = nullptr;
-
-    while (!context->stop &&
-           (!context->maxCount || (context->printCount < context->maxCount))) {
+    while (!max_count_ || print_count_ < max_count_) {
         struct log_msg log_msg;
-        int ret = android_logger_list_read(logger_list, &log_msg);
+        int ret = android_logger_list_read(logger_list.get(), &log_msg);
         if (!ret) {
-            logcat_panic(context, HELP_FALSE, "read: unexpected EOF!\n");
-            break;
+            error(EXIT_FAILURE, 0, R"init(Unexpected EOF!
+
+This means that either logd crashed, or more likely, this instance of logcat was unable to read log
+messages as quickly as they were being produced.
+
+If you have enabled significant logging, look into using the -G option to increase log buffer sizes.)init");
         }
 
         if (ret < 0) {
             if (ret == -EAGAIN) break;
 
             if (ret == -EIO) {
-                logcat_panic(context, HELP_FALSE, "read: unexpected EOF!\n");
-                break;
+                error(EXIT_FAILURE, 0, "Unexpected EOF!");
             }
             if (ret == -EINVAL) {
-                logcat_panic(context, HELP_FALSE, "read: unexpected length.\n");
-                break;
+                error(EXIT_FAILURE, 0, "Unexpected length.");
             }
-            logcat_panic(context, HELP_FALSE, "logcat read failure\n");
-            break;
+            error(EXIT_FAILURE, errno, "Logcat read failure");
         }
 
-        log_device_t* d;
-        for (d = context->devices; d; d = d->next) {
-            if (android_name_to_log_id(d->device) == log_msg.id()) break;
-        }
-        if (!d) {
-            context->devCount = 2; // set to Multiple
-            d = &unexpected;
-            d->binary = log_msg.id() == LOG_ID_EVENTS;
+        if (log_msg.id() > LOG_ID_MAX) {
+            error(EXIT_FAILURE, 0, "Unexpected log id (%d) over LOG_ID_MAX (%d).", log_msg.id(),
+                  LOG_ID_MAX);
         }
 
-        if (dev != d) {
-            dev = d;
-            maybePrintStart(context, dev, printDividers);
-            if (context->stop) break;
-        }
-        if (context->printBinary) {
-            printBinary(context, &log_msg);
+        PrintDividers(log_msg.id(), printDividers);
+
+        if (print_binary_) {
+            TEMP_FAILURE_RETRY(write(output_fd_.get(), &log_msg, log_msg.len()));
         } else {
-            processBuffer(context, dev, &log_msg);
+            ProcessBuffer(&log_msg);
         }
     }
-
-close:
-    // Short and sweet. Implemented generic version in android_logcat_destroy.
-    while (!!(dev = context->devices)) {
-        context->devices = dev->next;
-        delete dev;
-    }
-    android_logger_list_free(logger_list);
-
-exit:
-    // close write end of pipe to help things along
-    if (context->output_fd == context->fds[1]) {
-        android::close_output(context);
-    }
-    if (context->error_fd == context->fds[1]) {
-        android::close_error(context);
-    }
-    if (context->fds[1] >= 0) {
-        // NB: should be closed by the above
-        int save_errno = errno;
-        close(context->fds[1]);
-        errno = save_errno;
-        context->fds[1] = -1;
-    }
-    context->thread_stopped = true;
-    return context->retval;
+    return EXIT_SUCCESS;
 }
 
-// Can block
-int android_logcat_run_command(android_logcat_context ctx,
-                               int output, int error,
-                               int argc, char* const* argv,
-                               char* const* envp) {
-    android_logcat_context_internal* context = ctx;
-
-    context->output_fd = output;
-    context->error_fd = error;
-    context->argc = argc;
-    context->argv = argv;
-    context->envp = envp;
-    context->stop = false;
-    context->thread_stopped = false;
-    return __logcat(context);
-}
-
-// Finished with context
-int android_logcat_destroy(android_logcat_context* ctx) {
-    android_logcat_context_internal* context = *ctx;
-
-    if (!context) return -EBADF;
-
-    *ctx = nullptr;
-
-    context->stop = true;
-
-    while (context->thread_stopped == false) {
-        // Makes me sad, replace thread_stopped with semaphore.  Short lived.
-        sched_yield();
-    }
-
-    delete context->regex;
-    context->argv_hold.clear();
-    context->args.clear();
-    context->envp_hold.clear();
-    context->envs.clear();
-    if (context->fds[0] >= 0) {
-        close(context->fds[0]);
-        context->fds[0] = -1;
-    }
-    android::close_output(context);
-    android::close_error(context);
-
-    if (context->fds[1] >= 0) {
-        // NB: this should be closed by close_output, but just in case...
-        close(context->fds[1]);
-        context->fds[1] = -1;
-    }
-
-    android_closeEventTagMap(context->eventTagMap);
-
-    // generic cleanup of devices list to handle all possible dirty cases
-    log_device_t* dev;
-    while (!!(dev = context->devices)) {
-        struct logger_list* logger_list = dev->logger_list;
-        if (logger_list) {
-            for (log_device_t* d = dev; d; d = d->next) {
-                if (d->logger_list == logger_list) d->logger_list = nullptr;
-            }
-            android_logger_list_free(logger_list);
-        }
-        context->devices = dev->next;
-        delete dev;
-    }
-
-    int retval = context->retval;
-
-    free(context);
-
-    return retval;
+int main(int argc, char** argv) {
+    Logcat logcat;
+    return logcat.Run(argc, argv);
 }
diff --git a/logcat/logcat.h b/logcat/logcat.h
deleted file mode 100644
index 85ed7da..0000000
--- a/logcat/logcat.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2005-2017 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 <stdio.h>
-
-/*
- * The opaque context
- */
-typedef struct android_logcat_context_internal* android_logcat_context;
-
-/* Creates a context associated with this logcat instance
- *
- * Returns a pointer to the context, or a NULL on error.
- */
-android_logcat_context create_android_logcat();
-
-/* Collects and outputs the logcat data to output and error file descriptors
- *
- * Will block, performed in-thread and in-process
- *
- * The output file descriptor variable, if greater than or equal to 0, is
- * where the output (ie: stdout) will be sent. The file descriptor is closed
- * on android_logcat_destroy which terminates the instance, or when an -f flag
- * (output redirect to a file) is present in the command.  The error file
- * descriptor variable, if greater than or equal to 0, is where the error
- * stream (ie: stderr) will be sent, also closed on android_logcat_destroy.
- * The error file descriptor can be set to equal to the output file descriptor,
- * which will mix output and error stream content, and will defer closure of
- * the file descriptor on -f flag redirection.  Negative values for the file
- * descriptors will use stdout and stderr FILE references respectively
- * internally, and will not close the references as noted above.
- *
- * Return value is 0 for success, non-zero for errors.
- */
-int android_logcat_run_command(android_logcat_context ctx, int output, int error, int argc,
-                               char* const* argv, char* const* envp);
-
-/* Finished with context
- *
- * Kill the command thread ASAP (if any), and free up all associated resources.
- *
- * Return value is the result of the android_logcat_run_command, or
- * non-zero for any errors.
- */
-int android_logcat_destroy(android_logcat_context* ctx);
diff --git a/logcat/logcat_main.cpp b/logcat/logcat_main.cpp
deleted file mode 100644
index ecfa2ba..0000000
--- a/logcat/logcat_main.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2017 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 <signal.h>
-#include <stdlib.h>
-
-#include "logcat.h"
-
-int main(int argc, char** argv, char** envp) {
-    android_logcat_context ctx = create_android_logcat();
-    if (!ctx) return -1;
-    signal(SIGPIPE, exit);
-    int retval = android_logcat_run_command(ctx, -1, -1, argc, argv, envp);
-    int ret = android_logcat_destroy(&ctx);
-    if (!ret) ret = retval;
-    return ret;
-}
diff --git a/logcat/logcatd b/logcat/logcatd
new file mode 100755
index 0000000..622e567
--- /dev/null
+++ b/logcat/logcatd
@@ -0,0 +1,25 @@
+#! /system/bin/sh
+
+# This is primarily meant to be used by logpersist.  This script is run as an init service, which
+# first reads the 'last' logcat to persistent storage with `-L` then run logcat again without
+# `-L` to read the current logcat buffers to persistent storage.
+
+has_last="false"
+for arg in "$@"; do
+  if [ "$arg" == "-L" -o "$arg" == "--last" ]; then
+    has_last="true"
+  fi
+done
+
+if [ "$has_last" == "true" ]; then
+  logcat "$@"
+fi
+
+args_without_last=()
+for arg in "$@"; do
+  if [ "$arg" != "-L" -a "$arg" != "--last" ]; then
+    ARGS+=("$arg")
+  fi
+done
+
+exec logcat "${ARGS[@]}"
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index 07040b0..e986184 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -4,24 +4,22 @@
 # Make sure any property changes are only performed with /data mounted, after
 # post-fs-data state because otherwise behavior is undefined. The exceptions
 # are device adjustments for logcatd service properties (persist.* overrides
-# notwithstanding) for logd.logpersistd.size and logd.logpersistd.buffer.
+# notwithstanding) for logd.logpersistd.size logd.logpersistd.rotate_kbytes and
+# logd.logpersistd.buffer.
 
 # persist to non-persistent trampolines to permit device properties can be
 # overridden when /data mounts, or during runtime.
-on property:persist.logd.logpersistd.size=256
-    setprop persist.logd.logpersistd.size ""
-    setprop logd.logpersistd.size ""
+on property:persist.logd.logpersistd.count=*
+    # expect /init to report failure if property empty (default)
+    setprop persist.logd.logpersistd.size ${persist.logd.logpersistd.count}
 
 on property:persist.logd.logpersistd.size=*
-    # expect /init to report failure if property empty (default)
     setprop logd.logpersistd.size ${persist.logd.logpersistd.size}
 
-on property:persist.logd.logpersistd.buffer=all
-    setprop persist.logd.logpersistd.buffer ""
-    setprop logd.logpersistd.buffer ""
+on property:persist.logd.logpersistd.rotate_kbytes=*
+    setprop logd.logpersistd.rotate_kbytes ${persist.logd.logpersistd.rotate_kbytes}
 
 on property:persist.logd.logpersistd.buffer=*
-    # expect /init to report failure if property empty (default)
     setprop logd.logpersistd.buffer ${persist.logd.logpersistd.buffer}
 
 on property:persist.logd.logpersistd=logcatd
@@ -54,7 +52,7 @@
     stop logcatd
 
 # logcatd service
-service logcatd /system/bin/logcatd -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
+service logcatd /system/bin/logcatd -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r ${logd.logpersistd.rotate_kbytes:-2048} -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
     class late_start
     disabled
     # logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logcat/logcatd_main.cpp b/logcat/logcatd_main.cpp
deleted file mode 100644
index c131846..0000000
--- a/logcat/logcatd_main.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2017 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 <signal.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <string>
-#include <vector>
-
-#include "logcat.h"
-
-int main(int argc, char** argv, char** envp) {
-    android_logcat_context ctx = create_android_logcat();
-    if (!ctx) return -1;
-
-    signal(SIGPIPE, exit);
-
-    // Save and detect presence of -L or --last flag
-    std::vector<std::string> args;
-    bool last = false;
-    for (int i = 0; i < argc; ++i) {
-        if (!argv[i]) continue;
-        args.push_back(std::string(argv[i]));
-        if (!strcmp(argv[i], "-L") || !strcmp(argv[i], "--last")) last = true;
-    }
-
-    // Generate argv from saved content
-    std::vector<const char*> argv_hold;
-    for (auto& str : args) argv_hold.push_back(str.c_str());
-    argv_hold.push_back(nullptr);
-
-    int ret = 0;
-    if (last) {
-        // Run logcat command with -L flag
-        ret = android_logcat_run_command(ctx, -1, -1, argv_hold.size() - 1,
-                                         (char* const*)&argv_hold[0], envp);
-        // Remove -L and --last flags from argument list
-        for (std::vector<const char*>::iterator it = argv_hold.begin();
-             it != argv_hold.end();) {
-            if (!*it || (strcmp(*it, "-L") && strcmp(*it, "--last"))) {
-                ++it;
-            } else {
-                it = argv_hold.erase(it);
-            }
-        }
-        // fall through to re-run the command regardless of the arguments
-        // passed in.  For instance, we expect -h to report help stutter.
-    }
-
-    // Run logcat command without -L flag
-    int retval = android_logcat_run_command(ctx, -1, -1, argv_hold.size() - 1,
-                                            (char* const*)&argv_hold[0], envp);
-    if (!ret) ret = retval;
-    retval = android_logcat_destroy(&ctx);
-    if (!ret) ret = retval;
-    return ret;
-}
diff --git a/logcat/logpersist b/logcat/logpersist
index c09b6b2..05b46f0 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -148,9 +148,9 @@
     echo "WARNING: Can not use --size or --buffer with ${progname%.*}.stop" >&2
   fi
   if [ "true" = "${clear}" ]; then
-    setprop ${property} "clear"
+    setprop ${property#persist.} "clear"
   else
-    setprop ${property} "stop"
+    setprop ${property#persist.} "stop"
   fi
   if [ -n "`getprop ${property#persist.}.buffer`" ]; then
     setprop ${property}.buffer ""
diff --git a/logd/Android.bp b/logd/Android.bp
index 9b86258..b337b7c 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -39,7 +39,6 @@
         "FlushCommand.cpp",
         "LogBuffer.cpp",
         "LogBufferElement.cpp",
-        "LogBufferInterface.cpp",
         "LogTimes.cpp",
         "LogStatistics.cpp",
         "LogWhiteBlackList.cpp",
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index 7a843d8..694b5fa 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -19,6 +19,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <math.h>
 #include <netinet/in.h>
 #include <stdlib.h>
 #include <string.h>
@@ -186,14 +187,26 @@
     : LogCommand("getStatistics"), mBuf(*buf) {
 }
 
-static std::string package_string(const std::string& str) {
-    // Calculate total buffer size prefix, count is the string length w/o nul
-    char fmt[32];
-    for (size_t l = str.length(), y = 0, x = 6; y != x;
-         y = x, x = strlen(fmt) - 2) {
-        snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
+// This returns a string with a length prefix with the format <length>\n<data>\n\f.  The length
+// prefix includes the length of the prefix itself.
+static std::string PackageString(const std::string& str) {
+    size_t overhead_length = 3;  // \n \n \f.
+
+    // Number of digits needed to represent length(str + overhead_length).
+    size_t str_size_digits = 1 + static_cast<size_t>(log10(str.size() + overhead_length));
+    // Number of digits needed to represent the total size.
+    size_t total_size_digits =
+            1 + static_cast<size_t>(log10(str.size() + overhead_length + str_size_digits));
+
+    // If adding the size prefix causes a new digit to be required to represent the new total
+    // size, add it to the 'overhead_length'.  This can only happen once, since each new digit
+    // allows for 10x the previous size to be recorded.
+    if (total_size_digits != str_size_digits) {
+        overhead_length++;
     }
-    return android::base::StringPrintf(fmt, str.c_str());
+
+    size_t total_size = str.size() + overhead_length + str_size_digits;
+    return android::base::StringPrintf("%zu\n%s\n\f", total_size, str.c_str());
 }
 
 int CommandListener::GetStatisticsCmd::runCommand(SocketClient* cli, int argc,
@@ -228,8 +241,7 @@
         }
     }
 
-    cli->sendMsg(
-        package_string(mBuf.formatStatistics(uid, pid, logMask)).c_str());
+    cli->sendMsg(PackageString(mBuf.formatStatistics(uid, pid, logMask)).c_str());
     return 0;
 }
 
@@ -240,7 +252,7 @@
 int CommandListener::GetPruneListCmd::runCommand(SocketClient* cli,
                                                  int /*argc*/, char** /*argv*/) {
     setname();
-    cli->sendMsg(package_string(mBuf.formatPrune()).c_str());
+    cli->sendMsg(PackageString(mBuf.formatPrune()).c_str());
     return 0;
 }
 
@@ -316,12 +328,11 @@
             cli->sendMsg("can not mix id= with either format= or name=");
             return 0;
         }
-        cli->sendMsg(package_string(mBuf.formatEntry(atoi(id), uid)).c_str());
+        cli->sendMsg(PackageString(mBuf.formatEntry(atoi(id), uid)).c_str());
         return 0;
     }
 
-    cli->sendMsg(
-        package_string(mBuf.formatGetEventTag(uid, name, format)).c_str());
+    cli->sendMsg(PackageString(mBuf.formatGetEventTag(uid, name, format)).c_str());
 
     return 0;
 }
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index a21555c..d9cc0db 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -143,10 +143,6 @@
 
 void LogAudit::auditParse(const std::string& string, uid_t uid,
                           std::string* bug_num) {
-    if (!__android_log_is_debuggable()) {
-        bug_num->assign("");
-        return;
-    }
     static std::map<std::string, std::string> denial_to_bug =
         populateDenialMap();
     std::string scontext = denialParse(string, ':', "scontext=u:object_r:");
@@ -160,7 +156,7 @@
     }
     auto search = denial_to_bug.find(scontext + tcontext + tclass);
     if (search != denial_to_bug.end()) {
-        bug_num->assign(" b/" + search->second);
+        bug_num->assign(" " + search->second);
     } else {
         bug_num->assign("");
     }
@@ -229,70 +225,17 @@
         static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
         static const char newline[] = "\n";
 
-        // Dedupe messages, checking for identical messages starting with avc:
-        static unsigned count;
-        static char* last_str;
-        static bool last_info;
+        auditParse(str, uid, &denial_metadata);
+        iov[0].iov_base = info ? const_cast<char*>(log_info) : const_cast<char*>(log_warning);
+        iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
+        iov[1].iov_base = str;
+        iov[1].iov_len = strlen(str);
+        iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
+        iov[2].iov_len = denial_metadata.length();
+        iov[3].iov_base = const_cast<char*>(newline);
+        iov[3].iov_len = strlen(newline);
 
-        if (last_str != nullptr) {
-            static const char avc[] = "): avc: ";
-            char* avcl = strstr(last_str, avc);
-            bool skip = false;
-
-            if (avcl) {
-                char* avcr = strstr(str, avc);
-
-                skip = avcr &&
-                       !fastcmp<strcmp>(avcl + strlen(avc), avcr + strlen(avc));
-                if (skip) {
-                    ++count;
-                    free(last_str);
-                    last_str = strdup(str);
-                    last_info = info;
-                }
-            }
-            if (!skip) {
-                static const char resume[] = " duplicate messages suppressed\n";
-                iov[0].iov_base = last_info ? const_cast<char*>(log_info)
-                                            : const_cast<char*>(log_warning);
-                iov[0].iov_len =
-                    last_info ? sizeof(log_info) : sizeof(log_warning);
-                iov[1].iov_base = last_str;
-                iov[1].iov_len = strlen(last_str);
-                iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
-                iov[2].iov_len = denial_metadata.length();
-                if (count > 1) {
-                    iov[3].iov_base = const_cast<char*>(resume);
-                    iov[3].iov_len = strlen(resume);
-                } else {
-                    iov[3].iov_base = const_cast<char*>(newline);
-                    iov[3].iov_len = strlen(newline);
-                }
-
-                writev(fdDmesg, iov, arraysize(iov));
-                free(last_str);
-                last_str = nullptr;
-            }
-        }
-        if (last_str == nullptr) {
-            count = 0;
-            last_str = strdup(str);
-            last_info = info;
-        }
-        if (count == 0) {
-            auditParse(str, uid, &denial_metadata);
-            iov[0].iov_base = info ? const_cast<char*>(log_info)
-                                   : const_cast<char*>(log_warning);
-            iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
-            iov[1].iov_base = str;
-            iov[1].iov_len = strlen(str);
-            iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
-            iov[2].iov_len = denial_metadata.length();
-            iov[3].iov_base = const_cast<char*>(newline);
-            iov[3].iov_len = strlen(newline);
-
-            writev(fdDmesg, iov, arraysize(iov));
-        }
+        writev(fdDmesg, iov, arraysize(iov));
     }
 
     if (!main && !events) {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 9cbc7c4..834b20b 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -638,6 +638,8 @@
     if (stats.sizes(id) > (2 * log_buffer_size(id))) {  // +100%
         // A misbehaving or slow reader has its connection
         // dropped if we hit too much memory pressure.
+        android::prdebug("Kicking blocked reader, pid %d, from LogBuffer::kickMe()\n",
+                         me->mClient->getPid());
         me->release_Locked();
     } else if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
         // Allow a blocked WRAP timeout reader to
@@ -645,6 +647,9 @@
         me->triggerReader_Locked();
     } else {
         // tell slow reader to skip entries to catch up
+        android::prdebug(
+                "Skipping %lu entries from slow reader, pid %d, from LogBuffer::kickMe()\n",
+                pruneRows, me->mClient->getPid());
         me->triggerSkip_Locked(id, pruneRows);
     }
 }
@@ -1051,6 +1056,9 @@
                     LogTimeEntry* entry = times->get();
                     // Killer punch
                     if (entry->isWatching(id)) {
+                        android::prdebug(
+                                "Kicking blocked reader, pid %d, from LogBuffer::clear()\n",
+                                entry->mClient->getPid());
                         entry->release_Locked();
                     }
                     times++;
@@ -1185,7 +1193,7 @@
         unlock();
 
         // range locking in LastLogTimes looks after us
-        curr = element->flushTo(reader, this, privileged, sameTid);
+        curr = element->flushTo(reader, this, sameTid);
 
         if (curr == element->FLUSH_ERROR) {
             return curr;
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 774d4ab..c2d5b97 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -27,7 +27,6 @@
 #include <sysutils/SocketClient.h>
 
 #include "LogBufferElement.h"
-#include "LogBufferInterface.h"
 #include "LogStatistics.h"
 #include "LogTags.h"
 #include "LogTimes.h"
@@ -75,7 +74,7 @@
 
 typedef std::list<LogBufferElement*> LogBufferElementCollection;
 
-class LogBuffer : public LogBufferInterface {
+class LogBuffer {
     LogBufferElementCollection mLogElements;
     pthread_rwlock_t mLogElementsLock;
 
@@ -108,14 +107,14 @@
     LastLogTimes& mTimes;
 
     explicit LogBuffer(LastLogTimes* times);
-    ~LogBuffer() override;
+    ~LogBuffer();
     void init();
     bool isMonotonic() {
         return monotonic;
     }
 
-    int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
-            const char* msg, uint16_t len) override;
+    int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
+            uint16_t len);
     // lastTid is an optional context to help detect if the last previous
     // valid message was from the same source so we can differentiate chatty
     // filter types (identical or expired)
@@ -159,12 +158,7 @@
     const char* pidToName(pid_t pid) {
         return stats.pidToName(pid);
     }
-    virtual uid_t pidToUid(pid_t pid) override {
-        return stats.pidToUid(pid);
-    }
-    virtual pid_t tidToPid(pid_t tid) override {
-        return stats.tidToPid(tid);
-    }
+    uid_t pidToUid(pid_t pid) { return stats.pidToUid(pid); }
     const char* uidToName(uid_t uid) {
         return stats.uidToName(uid);
     }
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 2fd9f95..ec81933 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -56,14 +56,7 @@
       mLogId(elem.mLogId),
       mDropped(elem.mDropped) {
     if (mDropped) {
-        if (elem.isBinary() && elem.mMsg != nullptr) {
-            // for the following "len" value, refer to : setDropped(uint16_t value), getTag()
-            const int len = sizeof(android_event_header_t);
-            mMsg = new char[len];
-            memcpy(mMsg, elem.mMsg, len);
-        } else {
-            mMsg = nullptr;
-        }
+        mTag = elem.getTag();
     } else {
         mMsg = new char[mMsgLen];
         memcpy(mMsg, elem.mMsg, mMsgLen);
@@ -71,31 +64,43 @@
 }
 
 LogBufferElement::~LogBufferElement() {
-    delete[] mMsg;
+    if (!mDropped) {
+        delete[] mMsg;
+    }
 }
 
 uint32_t LogBufferElement::getTag() const {
-    return (isBinary() &&
-            ((mDropped && mMsg != nullptr) ||
-             (!mDropped && mMsgLen >= sizeof(android_event_header_t))))
-               ? reinterpret_cast<const android_event_header_t*>(mMsg)->tag
-               : 0;
+    // Binary buffers have no tag.
+    if (!isBinary()) {
+        return 0;
+    }
+
+    // Dropped messages store the tag in place of mMsg.
+    if (mDropped) {
+        return mTag;
+    }
+
+    // For non-dropped messages, we get the tag from the message header itself.
+    if (mMsgLen < sizeof(android_event_header_t)) {
+        return 0;
+    }
+
+    return reinterpret_cast<const android_event_header_t*>(mMsg)->tag;
 }
 
 uint16_t LogBufferElement::setDropped(uint16_t value) {
-    // The tag information is saved in mMsg data, if the tag is non-zero
-    // save only the information needed to get the tag.
-    if (getTag() != 0) {
-        if (mMsgLen > sizeof(android_event_header_t)) {
-            char* truncated_msg = new char[sizeof(android_event_header_t)];
-            memcpy(truncated_msg, mMsg, sizeof(android_event_header_t));
-            delete[] mMsg;
-            mMsg = truncated_msg;
-        }  // mMsgLen == sizeof(android_event_header_t), already at minimum.
-    } else {
-        delete[] mMsg;
-        mMsg = nullptr;
+    if (mDropped) {
+        return mDroppedCount = value;
     }
+
+    // The tag information is saved in mMsg data, which is in a union with mTag, used after mDropped
+    // is set to true. Therefore we save the tag value aside, delete mMsg, then set mTag to the tag
+    // value in its place.
+    auto old_tag = getTag();
+    delete[] mMsg;
+    mMsg = nullptr;
+
+    mTag = old_tag;
     mDropped = true;
     return mDroppedCount = value;
 }
@@ -239,14 +244,10 @@
     return retval;
 }
 
-log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent,
-                                   bool privileged, bool lastSame) {
-    struct logger_entry_v4 entry;
+log_time LogBufferElement::flushTo(SocketClient* reader, LogBuffer* parent, bool lastSame) {
+    struct logger_entry entry = {};
 
-    memset(&entry, 0, sizeof(struct logger_entry_v4));
-
-    entry.hdr_size = privileged ? sizeof(struct logger_entry_v4)
-                                : sizeof(struct logger_entry_v3);
+    entry.hdr_size = sizeof(struct logger_entry);
     entry.lid = mLogId;
     entry.pid = mPid;
     entry.tid = mTid;
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 57b0a95..fd790e4 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef _LOGD_LOG_BUFFER_ELEMENT_H__
-#define _LOGD_LOG_BUFFER_ELEMENT_H__
+#pragma once
 
 #include <stdatomic.h>
 #include <stdint.h>
@@ -41,7 +40,10 @@
     const uint32_t mPid;
     const uint32_t mTid;
     log_time mRealTime;
-    char* mMsg;
+    union {
+        char* mMsg;    // mDropped == false
+        int32_t mTag;  // mDropped == true
+    };
     union {
         const uint16_t mMsgLen;  // mDropped == false
         uint16_t mDroppedCount;  // mDropped == true
@@ -93,8 +95,5 @@
     }
 
     static const log_time FLUSH_ERROR;
-    log_time flushTo(SocketClient* writer, LogBuffer* parent, bool privileged,
-                     bool lastSame);
+    log_time flushTo(SocketClient* writer, LogBuffer* parent, bool lastSame);
 };
-
-#endif
diff --git a/logd/LogBufferInterface.cpp b/logd/LogBufferInterface.cpp
deleted file mode 100644
index 4b6d363..0000000
--- a/logd/LogBufferInterface.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2017 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 "LogBufferInterface.h"
-#include "LogUtils.h"
-
-LogBufferInterface::LogBufferInterface() {
-}
-LogBufferInterface::~LogBufferInterface() {
-}
-uid_t LogBufferInterface::pidToUid(pid_t pid) {
-    return android::pidToUid(pid);
-}
-pid_t LogBufferInterface::tidToPid(pid_t tid) {
-    return android::tidToPid(tid);
-}
diff --git a/logd/LogBufferInterface.h b/logd/LogBufferInterface.h
deleted file mode 100644
index f31e244..0000000
--- a/logd/LogBufferInterface.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2012-2014 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 _LOGD_LOG_BUFFER_INTERFACE_H__
-#define _LOGD_LOG_BUFFER_INTERFACE_H__
-
-#include <sys/types.h>
-
-#include <android-base/macros.h>
-#include <log/log_id.h>
-#include <log/log_time.h>
-
-// Abstract interface that handles log when log available.
-class LogBufferInterface {
-   public:
-    LogBufferInterface();
-    virtual ~LogBufferInterface();
-    // Handles a log entry when available in LogListener.
-    // Returns the size of the handled log message.
-    virtual int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
-                    pid_t tid, const char* msg, uint16_t len) = 0;
-
-    virtual uid_t pidToUid(pid_t pid);
-    virtual pid_t tidToPid(pid_t tid);
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(LogBufferInterface);
-};
-
-#endif  // _LOGD_LOG_BUFFER_INTERFACE_H__
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 2f22778..ba61042 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-#include <ctype.h>
 #include <limits.h>
-#include <stdio.h>
 #include <sys/cdefs.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
@@ -32,9 +30,8 @@
 #include "LogListener.h"
 #include "LogUtils.h"
 
-LogListener::LogListener(LogBufferInterface* buf, LogReader* reader)
-    : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {
-}
+LogListener::LogListener(LogBuffer* buf, LogReader* reader)
+    : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {}
 
 bool LogListener::onDataAvailable(SocketClient* cli) {
     static bool name_set;
@@ -44,8 +41,7 @@
     }
 
     // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received
-    char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) +
-                LOGGER_ENTRY_MAX_PAYLOAD + 1];
+    char buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1];
     struct iovec iov = { buffer, sizeof(buffer) - 1 };
 
     alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
@@ -78,11 +74,8 @@
         cmsg = CMSG_NXTHDR(&hdr, cmsg);
     }
 
-    struct ucred fake_cred;
     if (cred == nullptr) {
-        cred = &fake_cred;
-        cred->pid = 0;
-        cred->uid = DEFAULT_OVERFLOWUID;
+        return false;
     }
 
     if (cred->uid == AID_LOGD) {
@@ -106,40 +99,16 @@
         return false;
     }
 
-    // Check credential validity, acquire corrected details if not supplied.
-    if (cred->pid == 0) {
-        cred->pid = logbuf ? logbuf->tidToPid(header->tid)
-                           : android::tidToPid(header->tid);
-        if (cred->pid == getpid()) {
-            // We expect that /proc/<tid>/ is accessible to self even without
-            // readproc group, so that we will always drop messages that come
-            // from any of our logd threads and their library calls.
-            return false;  // ignore self
-        }
-    }
-    if (cred->uid == DEFAULT_OVERFLOWUID) {
-        uid_t uid =
-            logbuf ? logbuf->pidToUid(cred->pid) : android::pidToUid(cred->pid);
-        if (uid == AID_LOGD) {
-            uid = logbuf ? logbuf->pidToUid(header->tid)
-                         : android::pidToUid(cred->pid);
-        }
-        if (uid != AID_LOGD) cred->uid = uid;
-    }
-
     char* msg = ((char*)buffer) + sizeof(android_log_header_t);
     n -= sizeof(android_log_header_t);
 
     // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
     // truncated message to the logs.
 
-    if (logbuf != nullptr) {
-        int res = logbuf->log(
-            logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
-            ((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX);
-        if (res > 0 && reader != nullptr) {
-            reader->notifyNewLog(static_cast<log_mask_t>(1 << logId));
-        }
+    int res = logbuf->log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
+                          ((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX);
+    if (res > 0) {
+        reader->notifyNewLog(static_cast<log_mask_t>(1 << logId));
     }
 
     return true;
diff --git a/logd/LogListener.h b/logd/LogListener.h
index a562a54..8fe3da4 100644
--- a/logd/LogListener.h
+++ b/logd/LogListener.h
@@ -20,22 +20,12 @@
 #include <sysutils/SocketListener.h>
 #include "LogReader.h"
 
-// DEFAULT_OVERFLOWUID is defined in linux/highuid.h, which is not part of
-// the uapi headers for userspace to use.  This value is filled in on the
-// out-of-band socket credentials if the OS fails to find one available.
-// One of the causes of this is if SO_PASSCRED is set, all the packets before
-// that point will have this value.  We also use it in a fake credential if
-// no socket credentials are supplied.
-#ifndef DEFAULT_OVERFLOWUID
-#define DEFAULT_OVERFLOWUID 65534
-#endif
-
 class LogListener : public SocketListener {
-    LogBufferInterface* logbuf;
+    LogBuffer* logbuf;
     LogReader* reader;
 
    public:
-    LogListener(LogBufferInterface* buf, LogReader* reader /* nullable */);
+     LogListener(LogBuffer* buf, LogReader* reader);
 
    protected:
     virtual bool onDataAvailable(SocketClient* cli);
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 116e08e..431b778 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -837,35 +837,12 @@
     }
     return AID_LOGD;  // associate this with the logger
 }
-
-pid_t tidToPid(pid_t tid) {
-    char buffer[512];
-    snprintf(buffer, sizeof(buffer), "/proc/%u/status", tid);
-    FILE* fp = fopen(buffer, "r");
-    if (fp) {
-        while (fgets(buffer, sizeof(buffer), fp)) {
-            int pid = tid;
-            char space = 0;
-            if ((sscanf(buffer, "Tgid: %d%c", &pid, &space) == 2) &&
-                isspace(space)) {
-                fclose(fp);
-                return pid;
-            }
-        }
-        fclose(fp);
-    }
-    return tid;
-}
 }
 
 uid_t LogStatistics::pidToUid(pid_t pid) {
     return pidTable.add(pid)->second.getUid();
 }
 
-pid_t LogStatistics::tidToPid(pid_t tid) {
-    return tidTable.add(tid)->second.getPid();
-}
-
 // caller must free character string
 const char* LogStatistics::pidToName(pid_t pid) const {
     // An inconvenient truth ... getName() can alter the object
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 469f6dc..0782de3 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -306,6 +306,10 @@
     std::string format(const LogStatistics& stat, log_id_t id) const;
 };
 
+namespace android {
+uid_t pidToUid(pid_t pid);
+}
+
 struct PidEntry : public EntryBaseDropped {
     const pid_t pid;
     uid_t uid;
@@ -385,13 +389,6 @@
           uid(android::pidToUid(tid)),
           name(android::tidToName(tid)) {
     }
-    TidEntry(pid_t tid)
-        : EntryBaseDropped(),
-          tid(tid),
-          pid(android::tidToPid(tid)),
-          uid(android::pidToUid(tid)),
-          name(android::tidToName(tid)) {
-    }
     explicit TidEntry(const LogBufferElement* element)
         : EntryBaseDropped(element),
           tid(element->getTid()),
@@ -787,7 +784,6 @@
     // helper (must be locked directly or implicitly by mLogElementsLock)
     const char* pidToName(pid_t pid) const;
     uid_t pidToUid(pid_t pid);
-    pid_t tidToPid(pid_t tid);
     const char* uidToName(uid_t uid) const;
 };
 
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index f19e7b0..0cc7886 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -311,9 +311,7 @@
         if (log_msg.entry.len <= sizeof(uint32_t)) continue;
         uint32_t Tag = get4LE(msg);
         if (Tag != TAG_DEF_LOG_TAG) continue;
-        uid_t uid = (log_msg.entry.hdr_size >= sizeof(logger_entry_v4))
-                        ? log_msg.entry.uid
-                        : AID_ROOT;
+        uid_t uid = log_msg.entry.uid;
 
         std::string Name;
         std::string Format;
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index 4dcd3e7..fa9f398 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -38,8 +38,6 @@
 // Caller must own and free returned value
 char* pidToName(pid_t pid);
 char* tidToName(pid_t tid);
-uid_t pidToUid(pid_t pid);
-pid_t tidToPid(pid_t tid);
 
 // Furnished in LogTags.cpp. Thread safe.
 const char* tagToName(uint32_t tag);
diff --git a/logd/README.property b/logd/README.property
index da5f96f..d2a2cbb 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -17,10 +17,13 @@
 					 Responds to logcatd, clear and stop.
 logd.logpersistd.buffer          persist logpersistd buffers to collect
 logd.logpersistd.size            persist logpersistd size in MB
+logd.logpersistd.rotate_kbytes   	 persist logpersistd outout file size in KB.
 persist.logd.logpersistd   string        Enable logpersist daemon, "logcatd"
                                          turns on logcat -f in logd context.
 persist.logd.logpersistd.buffer    all   logpersistd buffers to collect
 persist.logd.logpersistd.size      256   logpersistd size in MB
+persist.logd.logpersistd.count     256   sets max number of rotated logs to <count>.
+persist.logd.logpersistd.rotate_kbytes   1024  logpersistd output file size in KB
 persist.logd.size          number  ro    Global default size of the buffer for
                                          all log ids at initial startup, at
                                          runtime use: logcat -b all -G <value>
diff --git a/mkbootimg/mkbootimg_dummy.cpp b/logd/fuzz/Android.bp
similarity index 63%
rename from mkbootimg/mkbootimg_dummy.cpp
rename to logd/fuzz/Android.bp
index 410d379..299242d 100644
--- a/mkbootimg/mkbootimg_dummy.cpp
+++ b/logd/fuzz/Android.bp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 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.
@@ -13,12 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include <abi_check/mkbootimg_abi_check.h>
-
-void mkbootimg_dummy(boot_img_hdr* hdr) {
-    // TODO: Hack to trigger abi checks, remove this.
-    if (hdr) {
-        hdr--;
-    }
+cc_fuzz {
+    name: "log_buffer_log_fuzzer",
+    srcs: [
+        "log_buffer_log_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libbase",
+        "libcutils",
+        "libselinux",
+        "liblog",
+        "liblogd",
+        "libcutils",
+    ],
+    cflags: ["-Werror"],
 }
diff --git a/logd/fuzz/log_buffer_log_fuzzer.cpp b/logd/fuzz/log_buffer_log_fuzzer.cpp
new file mode 100644
index 0000000..4d1589b
--- /dev/null
+++ b/logd/fuzz/log_buffer_log_fuzzer.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright 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 <string>
+
+#include "../LogBuffer.h"
+#include "../LogTimes.h"
+
+// We don't want to waste a lot of entropy on messages
+#define MAX_MSG_LENGTH 5
+
+// Tag IDs usually start at 1000, we only want to try 1000 through 1009
+#define MIN_TAG_ID 1000
+#define TAG_MOD 10
+
+namespace android {
+struct LogInput {
+  public:
+    log_id_t log_id;
+    log_time realtime;
+    uid_t uid;
+    pid_t pid;
+    pid_t tid;
+    unsigned int log_mask;
+};
+
+int write_log_messages(const uint8_t** pdata, size_t* data_left, LogBuffer* log_buffer) {
+    const uint8_t* data = *pdata;
+    const LogInput* logInput = reinterpret_cast<const LogInput*>(data);
+    data += sizeof(LogInput);
+    *data_left -= sizeof(LogInput);
+
+    uint32_t tag = MIN_TAG_ID + data[0] % TAG_MOD;
+    uint8_t msg_length = data[1] % MAX_MSG_LENGTH;
+    if (msg_length < 2) {
+        // Not enough data for message
+        return 0;
+    }
+
+    data += 2 * sizeof(uint8_t);
+    *data_left -= 2 * sizeof(uint8_t);
+
+    if (*data_left < msg_length) {
+        // Not enough data for tag and message
+        *pdata = data;
+        return 0;
+    }
+
+    // We need nullterm'd strings
+    char msg[sizeof(uint32_t) + MAX_MSG_LENGTH + sizeof(char)];
+    char* msg_only = msg + sizeof(uint32_t);
+    memcpy(msg, &tag, sizeof(uint32_t));
+    memcpy(msg_only, data, msg_length);
+    msg_only[msg_length] = '\0';
+    data += msg_length;
+    *data_left -= msg_length;
+
+    // Other elements not in enum.
+    log_id_t log_id = static_cast<log_id_t>(unsigned(logInput->log_id) % (LOG_ID_MAX + 1));
+    log_buffer->log(log_id, logInput->realtime, logInput->uid, logInput->pid, logInput->tid, msg,
+                    sizeof(uint32_t) + msg_length + 1);
+    log_buffer->formatStatistics(logInput->uid, logInput->pid, logInput->log_mask);
+    *pdata = data;
+    return 1;
+}
+
+// Because system/core/logd/main.cpp redefines these.
+void prdebug(char const* fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+}
+char* uidToName(uid_t) {
+    return strdup("fake");
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    // We want a random tag length and a random remaining message length
+    if (data == nullptr || size < sizeof(LogInput) + 2 * sizeof(uint8_t)) {
+        return 0;
+    }
+
+    LastLogTimes times;
+    LogBuffer log_buffer(&times);
+    size_t data_left = size;
+    const uint8_t** pdata = &data;
+
+    log_buffer.enableStatistics();
+    log_buffer.initPrune(nullptr);
+    // We want to get pruning code to get called.
+    log_id_for_each(i) { log_buffer.setSize(i, 10000); }
+
+    while (data_left >= sizeof(LogInput) + 2 * sizeof(uint8_t)) {
+        if (!write_log_messages(pdata, &data_left, &log_buffer)) {
+            return 0;
+        }
+    }
+
+    log_id_for_each(i) { log_buffer.clear(i); }
+    return 0;
+}
+}  // namespace android
diff --git a/logd/logd.rc b/logd/logd.rc
index 438419a..530f342 100644
--- a/logd/logd.rc
+++ b/logd/logd.rc
@@ -6,7 +6,8 @@
     file /dev/kmsg w
     user logd
     group logd system package_info readproc
-    capabilities SYSLOG AUDIT_CONTROL SETGID
+    capabilities SYSLOG AUDIT_CONTROL
+    priority 10
     writepid /dev/cpuset/system-background/tasks
 
 service logd-reinit /system/bin/logd --reinit
diff --git a/logd/main.cpp b/logd/main.cpp
index fd3cdf8..23bbf86 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -17,6 +17,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/capability.h>
 #include <poll.h>
 #include <sched.h>
 #include <semaphore.h>
@@ -57,35 +58,10 @@
     '<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
         '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, '>'
 
-//
-// The service is designed to be run by init, it does not respond well
-// to starting up manually. When starting up manually the sockets will
-// fail to open typically for one of the following reasons:
-//     EADDRINUSE if logger is running.
-//     EACCESS if started without precautions (below)
-//
-// Here is a cookbook procedure for starting up logd manually assuming
-// init is out of the way, pedantically all permissions and SELinux
-// security is put back in place:
-//
-//    setenforce 0
-//    rm /dev/socket/logd*
-//    chmod 777 /dev/socket
-//        # here is where you would attach the debugger or valgrind for example
-//    runcon u:r:logd:s0 /system/bin/logd </dev/null >/dev/null 2>&1 &
-//    sleep 1
-//    chmod 755 /dev/socket
-//    chown logd.logd /dev/socket/logd*
-//    restorecon /dev/socket/logd*
-//    setenforce 1
-//
-// If minimalism prevails, typical for debugging and security is not a concern:
-//
-//    setenforce 0
-//    chmod 777 /dev/socket
-//    logd
-//
-
+// The service is designed to be run by init, it does not respond well to starting up manually. Init
+// has a 'sigstop' feature that sends SIGSTOP to a service immediately before calling exec().  This
+// allows debuggers, etc to be attached to logd at the very beginning, while still having init
+// handle the user, groups, capabilities, files, etc setup.
 static int drop_privs(bool klogd, bool auditd) {
     sched_param param = {};
 
@@ -99,11 +75,6 @@
         return -1;
     }
 
-    if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
-        android::prdebug("failed to set background cgroup");
-        return -1;
-    }
-
     if (!__android_logger_property_get_bool("ro.debuggable",
                                             BOOL_DEFAULT_FALSE) &&
         prctl(PR_SET_DUMPABLE, 0) == -1) {
@@ -111,52 +82,26 @@
         return -1;
     }
 
-    std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(),
-                                                             cap_free);
-    if (cap_clear(caps.get()) < 0) return -1;
-    cap_value_t cap_value[] = { CAP_SETGID,  // must be first for below
-                                klogd ? CAP_SYSLOG : CAP_SETGID,
-                                auditd ? CAP_AUDIT_CONTROL : CAP_SETGID };
-    if (cap_set_flag(caps.get(), CAP_PERMITTED, arraysize(cap_value), cap_value,
-                     CAP_SET) < 0) {
+    std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(), cap_free);
+    if (cap_clear(caps.get()) < 0) {
         return -1;
     }
-    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, arraysize(cap_value), cap_value,
-                     CAP_SET) < 0) {
+    std::vector<cap_value_t> cap_value;
+    if (klogd) {
+        cap_value.emplace_back(CAP_SYSLOG);
+    }
+    if (auditd) {
+        cap_value.emplace_back(CAP_AUDIT_CONTROL);
+    }
+
+    if (cap_set_flag(caps.get(), CAP_PERMITTED, cap_value.size(), cap_value.data(), CAP_SET) < 0) {
+        return -1;
+    }
+    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, cap_value.size(), cap_value.data(), CAP_SET) < 0) {
         return -1;
     }
     if (cap_set_proc(caps.get()) < 0) {
-        android::prdebug(
-            "failed to set CAP_SETGID, CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)",
-            errno);
-        return -1;
-    }
-
-    gid_t groups[] = { AID_READPROC };
-
-    if (setgroups(arraysize(groups), groups) == -1) {
-        android::prdebug("failed to set AID_READPROC groups");
-        return -1;
-    }
-
-    if (setgid(AID_LOGD) != 0) {
-        android::prdebug("failed to set AID_LOGD gid");
-        return -1;
-    }
-
-    if (setuid(AID_LOGD) != 0) {
-        android::prdebug("failed to set AID_LOGD uid");
-        return -1;
-    }
-
-    if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, cap_value, CAP_CLEAR) < 0) {
-        return -1;
-    }
-    if (cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, cap_value, CAP_CLEAR) < 0) {
-        return -1;
-    }
-    if (cap_set_proc(caps.get()) < 0) {
-        android::prdebug("failed to clear CAP_SETGID (%d)", errno);
+        android::prdebug("failed to set CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)", errno);
         return -1;
     }
 
@@ -205,67 +150,14 @@
     }
 }
 
-static sem_t uidName;
-static uid_t uid;
-static char* name;
-
 static sem_t reinit;
 static bool reinit_running = false;
 static LogBuffer* logBuf = nullptr;
 
-static bool package_list_parser_cb(pkg_info* info, void* /* userdata */) {
-    bool rc = true;
-    if (info->uid == uid) {
-        name = strdup(info->name);
-        // false to stop processing
-        rc = false;
-    }
-
-    packagelist_free(info);
-    return rc;
-}
-
 static void* reinit_thread_start(void* /*obj*/) {
     prctl(PR_SET_NAME, "logd.daemon");
-    set_sched_policy(0, SP_BACKGROUND);
-    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);
-
-    // We should drop to AID_LOGD, if we are anything else, we have
-    // even lesser privileges and accept our fate.
-    gid_t groups[] = {
-        AID_SYSTEM,        // search access to /data/system path
-        AID_PACKAGE_INFO,  // readonly access to /data/system/packages.list
-    };
-    if (setgroups(arraysize(groups), groups) == -1) {
-        android::prdebug(
-            "logd.daemon: failed to set AID_SYSTEM AID_PACKAGE_INFO groups");
-    }
-    if (setgid(AID_LOGD) != 0) {
-        android::prdebug("logd.daemon: failed to set AID_LOGD gid");
-    }
-    if (setuid(AID_LOGD) != 0) {
-        android::prdebug("logd.daemon: failed to set AID_LOGD uid");
-    }
-
-    cap_t caps = cap_init();
-    (void)cap_clear(caps);
-    (void)cap_set_proc(caps);
-    (void)cap_free(caps);
 
     while (reinit_running && !sem_wait(&reinit) && reinit_running) {
-        // uidToName Privileged Worker
-        if (uid) {
-            name = nullptr;
-
-            // if we got the perms wrong above, this would spam if we reported
-            // problems with acquisition of an uid name from the packages.
-            (void)packagelist_parse(package_list_parser_cb, nullptr);
-
-            uid = 0;
-            sem_post(&uidName);
-            continue;
-        }
-
         if (fdDmesg >= 0) {
             static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
                                                    'l',
@@ -302,26 +194,30 @@
     return nullptr;
 }
 
-static sem_t sem_name;
-
 char* android::uidToName(uid_t u) {
-    if (!u || !reinit_running) {
-        return nullptr;
-    }
+    struct Userdata {
+        uid_t uid;
+        char* name;
+    } userdata = {
+            .uid = u,
+            .name = nullptr,
+    };
 
-    sem_wait(&sem_name);
+    packagelist_parse(
+            [](pkg_info* info, void* callback_parameter) {
+                auto userdata = reinterpret_cast<Userdata*>(callback_parameter);
+                bool result = true;
+                if (info->uid == userdata->uid) {
+                    userdata->name = strdup(info->name);
+                    // false to stop processing
+                    result = false;
+                }
+                packagelist_free(info);
+                return result;
+            },
+            &userdata);
 
-    // Not multi-thread safe, we use sem_name to protect
-    uid = u;
-
-    name = nullptr;
-    sem_post(&reinit);
-    sem_wait(&uidName);
-    char* ret = name;
-
-    sem_post(&sem_name);
-
-    return ret;
+    return userdata.name;
 }
 
 // Serves as a global method to trigger reinitialization
@@ -373,11 +269,6 @@
 }
 
 static int issueReinit() {
-    cap_t caps = cap_init();
-    (void)cap_clear(caps);
-    (void)cap_set_proc(caps);
-    (void)cap_free(caps);
-
     int sock = TEMP_FAILURE_RETRY(socket_local_client(
         "logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
     if (sock < 0) return -errno;
@@ -440,10 +331,13 @@
         if (fdPmesg < 0) android::prdebug("Failed to open %s\n", proc_kmsg);
     }
 
+    bool auditd = __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
+    if (drop_privs(klogd, auditd) != 0) {
+        return EXIT_FAILURE;
+    }
+
     // Reinit Thread
     sem_init(&reinit, 0, 0);
-    sem_init(&uidName, 0, 0);
-    sem_init(&sem_name, 0, 1);
     pthread_attr_t attr;
     if (!pthread_attr_init(&attr)) {
         struct sched_param param;
@@ -461,12 +355,6 @@
         pthread_attr_destroy(&attr);
     }
 
-    bool auditd =
-        __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
-    if (drop_privs(klogd, auditd) != 0) {
-        return EXIT_FAILURE;
-    }
-
     // Serves the purpose of managing the last logs times read on a
     // socket connection, and as a reader lock on a range of log
     // entries.
diff --git a/logd/tests/Android.bp b/logd/tests/Android.bp
index 83a194f..d39da8a 100644
--- a/logd/tests/Android.bp
+++ b/logd/tests/Android.bp
@@ -35,12 +35,12 @@
 
     srcs: ["logd_test.cpp"],
 
-    shared_libs: [
+    static_libs: [
         "libbase",
         "libcutils",
         "libselinux",
+        "liblog",
     ],
-    static_libs: ["liblog"],
 }
 
 // Build tests for the logger. Run with:
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index b6c33d7..f47bee1 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -241,47 +241,18 @@
 static void caught_signal(int /* signum */) {
 }
 
-static void dump_log_msg(const char* prefix, log_msg* msg, unsigned int version,
-                         int lid) {
+static void dump_log_msg(const char* prefix, log_msg* msg, int lid) {
     std::cout << std::flush;
     std::cerr << std::flush;
     fflush(stdout);
     fflush(stderr);
-    switch (msg->entry.hdr_size) {
-        case 0:
-            version = 1;
-            break;
+    EXPECT_EQ(sizeof(logger_entry), msg->entry.hdr_size);
 
-        case sizeof(msg->entry_v2): /* PLUS case sizeof(msg->entry_v3): */
-            if (version == 0) {
-                version = (msg->entry_v3.lid < LOG_ID_MAX) ? 3 : 2;
-            }
-            break;
-
-        case sizeof(msg->entry_v4):
-            if (version == 0) {
-                version = 4;
-            }
-            break;
-    }
-
-    fprintf(stderr, "%s: v%u[%u] ", prefix, version, msg->len());
-    if (version != 1) {
-        fprintf(stderr, "hdr_size=%u ", msg->entry.hdr_size);
-    }
-    fprintf(stderr, "pid=%u tid=%u %u.%09u ", msg->entry.pid, msg->entry.tid,
-            msg->entry.sec, msg->entry.nsec);
-    switch (version) {
-        case 1:
-            break;
-        case 2:
-            fprintf(stderr, "euid=%u ", msg->entry_v2.euid);
-            break;
-        case 3:
-        default:
-            lid = msg->entry.lid;
-            break;
-    }
+    fprintf(stderr, "%s: [%u] ", prefix, msg->len());
+    fprintf(stderr, "hdr_size=%u ", msg->entry.hdr_size);
+    fprintf(stderr, "pid=%u tid=%u %u.%09u ", msg->entry.pid, msg->entry.tid, msg->entry.sec,
+            msg->entry.nsec);
+    lid = msg->entry.lid;
 
     switch (lid) {
         case 0:
@@ -349,86 +320,6 @@
 }
 #endif
 
-TEST(logd, both) {
-#ifdef __ANDROID__
-    log_msg msg;
-
-    // check if we can read any logs from logd
-    bool user_logger_available = false;
-    bool user_logger_content = false;
-
-    int fd = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
-                                 SOCK_SEQPACKET);
-    if (fd >= 0) {
-        struct sigaction ignore, old_sigaction;
-        memset(&ignore, 0, sizeof(ignore));
-        ignore.sa_handler = caught_signal;
-        sigemptyset(&ignore.sa_mask);
-        sigaction(SIGALRM, &ignore, &old_sigaction);
-        unsigned int old_alarm = alarm(10);
-
-        static const char ask[] = "dumpAndClose lids=0,1,2,3";
-        user_logger_available = write(fd, ask, sizeof(ask)) == sizeof(ask);
-
-        user_logger_content = recv(fd, msg.buf, sizeof(msg), 0) > 0;
-
-        if (user_logger_content) {
-            dump_log_msg("user", &msg, 3, -1);
-        }
-
-        alarm(old_alarm);
-        sigaction(SIGALRM, &old_sigaction, nullptr);
-
-        close(fd);
-    }
-
-    // check if we can read any logs from kernel logger
-    bool kernel_logger_available = false;
-    bool kernel_logger_content = false;
-
-    static const char* loggers[] = {
-        "/dev/log/main",   "/dev/log_main",   "/dev/log/radio",
-        "/dev/log_radio",  "/dev/log/events", "/dev/log_events",
-        "/dev/log/system", "/dev/log_system",
-    };
-
-    for (unsigned int i = 0; i < arraysize(loggers); ++i) {
-        fd = open(loggers[i], O_RDONLY);
-        if (fd < 0) {
-            continue;
-        }
-        kernel_logger_available = true;
-        fcntl(fd, F_SETFL, O_RDONLY | O_NONBLOCK);
-        int result = TEMP_FAILURE_RETRY(read(fd, msg.buf, sizeof(msg)));
-        if (result > 0) {
-            kernel_logger_content = true;
-            dump_log_msg("kernel", &msg, 0, i / 2);
-        }
-        close(fd);
-    }
-
-    static const char yes[] = "\xE2\x9C\x93";
-    static const char no[] = "\xE2\x9c\x98";
-    fprintf(stderr,
-            "LOGGER  Available  Content\n"
-            "user    %-13s%s\n"
-            "kernel  %-13s%s\n"
-            " status %-11s%s\n",
-            (user_logger_available) ? yes : no, (user_logger_content) ? yes : no,
-            (kernel_logger_available) ? yes : no,
-            (kernel_logger_content) ? yes : no,
-            (user_logger_available && kernel_logger_available) ? "ERROR" : "ok",
-            (user_logger_content && kernel_logger_content) ? "ERROR" : "ok");
-
-    EXPECT_EQ(0, user_logger_available && kernel_logger_available);
-    EXPECT_EQ(0, !user_logger_available && !kernel_logger_available);
-    EXPECT_EQ(0, user_logger_content && kernel_logger_content);
-    EXPECT_EQ(0, !user_logger_content && !kernel_logger_content);
-#else
-    GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
 #ifdef __ANDROID__
 // BAD ROBOT
 //   Benchmark threshold are generally considered bad form unless there is
@@ -664,11 +555,11 @@
     }
 
     if (content_wrap) {
-        dump_log_msg("wrap", &msg_wrap, 3, -1);
+        dump_log_msg("wrap", &msg_wrap, -1);
     }
 
     if (content_timeout) {
-        dump_log_msg("timeout", &msg_timeout, 3, -1);
+        dump_log_msg("timeout", &msg_timeout, -1);
     }
 
     EXPECT_TRUE(written);
@@ -801,11 +692,11 @@
     }
 
     if (content_wrap) {
-        dump_log_msg("wrap", &msg_wrap, 3, -1);
+        dump_log_msg("wrap", &msg_wrap, -1);
     }
 
     if (content_timeout) {
-        dump_log_msg("timeout", &msg_timeout, 3, -1);
+        dump_log_msg("timeout", &msg_timeout, -1);
     }
 
     if (content_wrap || !content_timeout) {
@@ -856,7 +747,7 @@
 
     EXPECT_TRUE(read_one);
     if (read_one) {
-        dump_log_msg("user", &msg, 3, -1);
+        dump_log_msg("user", &msg, -1);
     }
 
     fprintf(stderr, "Sleep for >%d seconds logd SO_SNDTIMEO ...\n", sndtimeo);
@@ -874,7 +765,7 @@
 
     EXPECT_EQ(0, recv_ret);
     if (recv_ret > 0) {
-        dump_log_msg("user", &msg, 3, -1);
+        dump_log_msg("user", &msg, -1);
     }
     EXPECT_EQ(0, save_errno);
 
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index c378646..8851a47 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -13,11 +13,12 @@
     name: "liblogwrap",
     defaults: ["logwrapper_defaults"],
     recovery_available: true,
-    srcs: ["logwrap.c"],
+    srcs: ["logwrap.cpp"],
     shared_libs: [
         "libcutils",
         "liblog",
     ],
+    header_libs: ["libbase_headers"],
     export_include_dirs: ["include"],
     local_include_dirs: ["include"],
 }
@@ -31,9 +32,10 @@
     defaults: ["logwrapper_defaults"],
     local_include_dirs: ["include"],
     srcs: [
-        "logwrap.c",
-        "logwrapper.c",
+        "logwrap.cpp",
+        "logwrapper.cpp",
     ],
+    header_libs: ["libbase_headers"],
     shared_libs: ["libcutils", "liblog"],
 }
 
@@ -54,10 +56,10 @@
 // ========================================================
 
 cc_benchmark {
-    name: "android_fork_execvp_ext_benchmark",
+    name: "logwrap_fork_execvp_benchmark",
     defaults: ["logwrapper_defaults"],
     srcs: [
-        "android_fork_execvp_ext_benchmark.cpp",
+        "logwrap_fork_execvp_benchmark.cpp",
     ],
     shared_libs: [
         "libbase",
diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h
index d3538b3..cb40ee2 100644
--- a/logwrapper/include/logwrap/logwrap.h
+++ b/logwrapper/include/logwrap/logwrap.h
@@ -15,23 +15,11 @@
  * limitations under the License.
  */
 
-#ifndef __LIBS_LOGWRAP_H
-#define __LIBS_LOGWRAP_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-__BEGIN_DECLS
+#pragma once
 
 /*
  * Run a command while logging its stdout and stderr
  *
- * WARNING: while this function is running it will clear all SIGCHLD handlers
- * if you rely on SIGCHLD in the caller there is a chance zombies will be
- * created if you're not calling waitpid after calling this. This function will
- * log a warning when it clears SIGCHLD for processes other than the child it
- * created.
- *
  * Arguments:
  *   argc:   the number of elements in argv
  *   argv:   an array of strings containing the command to be executed and its
@@ -40,10 +28,10 @@
  *   status: the equivalent child status as populated by wait(status). This
  *           value is only valid when logwrap successfully completes. If NULL
  *           the return value of the child will be the function's return value.
- *   ignore_int_quit: set to true if you want to completely ignore SIGINT and
- *           SIGQUIT while logwrap is running. This may force the end-user to
- *           send a signal twice to signal the caller (once for the child, and
- *           once for the caller)
+ *   forward_signals: set to true if you want to forward SIGINT, SIGQUIT, and
+ *           SIGHUP to the child process, while it is running.  You likely do
+ *           not need to use this; it is primarily for the logwrapper
+ *           executable itself.
  *   log_target: Specify where to log the output of the child, either LOG_NONE,
  *           LOG_ALOG (for the Android system log), LOG_KLOG (for the kernel
  *           log), or LOG_FILE (and you need to specify a pathname in the
@@ -54,8 +42,6 @@
  *           the specified log until the child has exited.
  *   file_path: if log_target has the LOG_FILE bit set, then this parameter
  *           must be set to the pathname of the file to log to.
- *   unused_opts: currently unused.
- *   unused_opts_len: currently unused.
  *
  * Return value:
  *   0 when logwrap successfully run the child process and captured its status
@@ -65,29 +51,11 @@
  *
  */
 
-/* Values for the log_target parameter android_fork_execvp_ext() */
+/* Values for the log_target parameter logwrap_fork_execvp() */
 #define LOG_NONE        0
 #define LOG_ALOG        1
 #define LOG_KLOG        2
 #define LOG_FILE        4
 
-// TODO: Remove unused_opts / unused_opts_len in a followup change.
-int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated, char *file_path, void* unused_opts,
-        int unused_opts_len);
-
-/* Similar to above, except abbreviated logging is not available, and if logwrap
- * is true, logging is to the Android system log, and if false, there is no
- * logging.
- */
-static inline int android_fork_execvp(int argc, char* argv[], int *status,
-                                     bool ignore_int_quit, bool logwrap)
-{
-    return android_fork_execvp_ext(argc, argv, status, ignore_int_quit,
-                                   (logwrap ? LOG_ALOG : LOG_NONE), false, NULL,
-                                   NULL, 0);
-}
-
-__END_DECLS
-
-#endif /* __LIBS_LOGWRAP_H */
+int logwrap_fork_execvp(int argc, const char* const* argv, int* status, bool forward_signals,
+                        int log_target, bool abbreviated, const char* file_path);
diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.cpp
similarity index 62%
rename from logwrapper/logwrap.c
rename to logwrapper/logwrap.cpp
index 8621993..5337801 100644
--- a/logwrapper/logwrap.c
+++ b/logwrapper/logwrap.cpp
@@ -19,7 +19,6 @@
 #include <libgen.h>
 #include <poll.h>
 #include <pthread.h>
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -28,26 +27,31 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <algorithm>
+
+#include <android-base/macros.h>
 #include <cutils/klog.h>
 #include <log/log.h>
 #include <logwrap/logwrap.h>
 
-#define ARRAY_SIZE(x)   (sizeof(x) / sizeof(*(x)))
-#define MIN(a,b) (((a)<(b))?(a):(b))
-
 static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
+// Protected by fd_mutex.  These signals must be blocked while modifying as well.
+static pid_t child_pid;
+static struct sigaction old_int;
+static struct sigaction old_quit;
+static struct sigaction old_hup;
 
-#define ERROR(fmt, args...)                                                   \
-do {                                                                          \
-    fprintf(stderr, fmt, ## args);                                            \
-    ALOG(LOG_ERROR, "logwrapper", fmt, ## args);                              \
-} while(0)
+#define ERROR(fmt, args...)                         \
+    do {                                            \
+        fprintf(stderr, fmt, ##args);               \
+        ALOG(LOG_ERROR, "logwrapper", fmt, ##args); \
+    } while (0)
 
-#define FATAL_CHILD(fmt, args...)                                             \
-do {                                                                          \
-    ERROR(fmt, ## args);                                                      \
-    _exit(-1);                                                                \
-} while(0)
+#define FATAL_CHILD(fmt, args...) \
+    do {                          \
+        ERROR(fmt, ##args);       \
+        _exit(-1);                \
+    } while (0)
 
 #define MAX_KLOG_TAG 16
 
@@ -56,7 +60,7 @@
  */
 #define BEGINNING_BUF_SIZE 0x1000
 struct beginning_buf {
-    char *buf;
+    char* buf;
     size_t alloc_len;
     /* buf_size is the usable space, which is one less than the allocated size */
     size_t buf_size;
@@ -69,7 +73,7 @@
  */
 #define ENDING_BUF_SIZE 0x1000
 struct ending_buf {
-    char *buf;
+    char* buf;
     ssize_t alloc_len;
     /* buf_size is the usable space, which is one less than the allocated size */
     ssize_t buf_size;
@@ -79,7 +83,7 @@
     int write;
 };
 
- /* A structure to hold all the abbreviated buf data */
+/* A structure to hold all the abbreviated buf data */
 struct abbr_buf {
     struct beginning_buf b_buf;
     struct ending_buf e_buf;
@@ -90,19 +94,17 @@
 struct log_info {
     int log_target;
     char klog_fmt[MAX_KLOG_TAG * 2];
-    char *btag;
+    const char* btag;
     bool abbreviated;
-    FILE *fp;
+    FILE* fp;
     struct abbr_buf a_buf;
 };
 
 /* Forware declaration */
-static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen);
+static void add_line_to_abbr_buf(struct abbr_buf* a_buf, char* linebuf, int linelen);
 
 /* Return 0 on success, and 1 when full */
-static int add_line_to_linear_buf(struct beginning_buf *b_buf,
-                                   char *line, ssize_t line_len)
-{
+static int add_line_to_linear_buf(struct beginning_buf* b_buf, char* line, ssize_t line_len) {
     int full = 0;
 
     if ((line_len + b_buf->used_len) > b_buf->buf_size) {
@@ -116,20 +118,18 @@
     return full;
 }
 
-static void add_line_to_circular_buf(struct ending_buf *e_buf,
-                                     char *line, ssize_t line_len)
-{
+static void add_line_to_circular_buf(struct ending_buf* e_buf, char* line, ssize_t line_len) {
     ssize_t free_len;
     ssize_t needed_space;
     int cnt;
 
-    if (e_buf->buf == NULL) {
+    if (e_buf->buf == nullptr) {
         return;
     }
 
-   if (line_len > e_buf->buf_size) {
-       return;
-   }
+    if (line_len > e_buf->buf_size) {
+        return;
+    }
 
     free_len = e_buf->buf_size - e_buf->used_len;
 
@@ -144,7 +144,7 @@
     /* Copy the line into the circular buffer, dealing with possible
      * wraparound.
      */
-    cnt = MIN(line_len, e_buf->buf_size - e_buf->write);
+    cnt = std::min(line_len, e_buf->buf_size - e_buf->write);
     memcpy(e_buf->buf + e_buf->write, line, cnt);
     if (cnt < line_len) {
         memcpy(e_buf->buf, line + cnt, line_len - cnt);
@@ -154,7 +154,7 @@
 }
 
 /* Log directly to the specified log */
-static void do_log_line(struct log_info *log_info, char *line) {
+static void do_log_line(struct log_info* log_info, const char* line) {
     if (log_info->log_target & LOG_KLOG) {
         klog_write(6, log_info->klog_fmt, line);
     }
@@ -169,7 +169,7 @@
 /* Log to either the abbreviated buf, or directly to the specified log
  * via do_log_line() above.
  */
-static void log_line(struct log_info *log_info, char *line, int len) {
+static void log_line(struct log_info* log_info, char* line, int len) {
     if (log_info->abbreviated) {
         add_line_to_abbr_buf(&log_info->a_buf, line, len);
     } else {
@@ -184,9 +184,8 @@
  * than buf_size (the usable size of the buffer) to make sure there is
  * room to temporarily stuff a null byte to terminate a line for logging.
  */
-static void print_buf_lines(struct log_info *log_info, char *buf, int buf_size)
-{
-    char *line_start;
+static void print_buf_lines(struct log_info* log_info, char* buf, int buf_size) {
+    char* line_start;
     char c;
     int i;
 
@@ -212,17 +211,17 @@
      */
 }
 
-static void init_abbr_buf(struct abbr_buf *a_buf) {
-    char *new_buf;
+static void init_abbr_buf(struct abbr_buf* a_buf) {
+    char* new_buf;
 
     memset(a_buf, 0, sizeof(struct abbr_buf));
-    new_buf = malloc(BEGINNING_BUF_SIZE);
+    new_buf = static_cast<char*>(malloc(BEGINNING_BUF_SIZE));
     if (new_buf) {
         a_buf->b_buf.buf = new_buf;
         a_buf->b_buf.alloc_len = BEGINNING_BUF_SIZE;
         a_buf->b_buf.buf_size = BEGINNING_BUF_SIZE - 1;
     }
-    new_buf = malloc(ENDING_BUF_SIZE);
+    new_buf = static_cast<char*>(malloc(ENDING_BUF_SIZE));
     if (new_buf) {
         a_buf->e_buf.buf = new_buf;
         a_buf->e_buf.alloc_len = ENDING_BUF_SIZE;
@@ -230,23 +229,22 @@
     }
 }
 
-static void free_abbr_buf(struct abbr_buf *a_buf) {
+static void free_abbr_buf(struct abbr_buf* a_buf) {
     free(a_buf->b_buf.buf);
     free(a_buf->e_buf.buf);
 }
 
-static void add_line_to_abbr_buf(struct abbr_buf *a_buf, char *linebuf, int linelen) {
+static void add_line_to_abbr_buf(struct abbr_buf* a_buf, char* linebuf, int linelen) {
     if (!a_buf->beginning_buf_full) {
-        a_buf->beginning_buf_full =
-            add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen);
+        a_buf->beginning_buf_full = add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen);
     }
     if (a_buf->beginning_buf_full) {
         add_line_to_circular_buf(&a_buf->e_buf, linebuf, linelen);
     }
 }
 
-static void print_abbr_buf(struct log_info *log_info) {
-    struct abbr_buf *a_buf = &log_info->a_buf;
+static void print_abbr_buf(struct log_info* log_info) {
+    struct abbr_buf* a_buf = &log_info->a_buf;
 
     /* Add the abbreviated output to the kernel log */
     if (a_buf->b_buf.alloc_len) {
@@ -269,14 +267,13 @@
      * and then cal print_buf_lines on it */
     if (a_buf->e_buf.read < a_buf->e_buf.write) {
         /* no wrap around, just print it */
-        print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read,
-                        a_buf->e_buf.used_len);
+        print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read, a_buf->e_buf.used_len);
     } else {
         /* The circular buffer will always have at least 1 byte unused,
          * so by allocating alloc_len here we will have at least
          * 1 byte of space available as required by print_buf_lines().
          */
-        char * nbuf = malloc(a_buf->e_buf.alloc_len);
+        char* nbuf = static_cast<char*>(malloc(a_buf->e_buf.alloc_len));
         if (!nbuf) {
             return;
         }
@@ -289,15 +286,54 @@
     }
 }
 
-static int parent(const char *tag, int parent_read, pid_t pid,
-        int *chld_sts, int log_target, bool abbreviated, char *file_path) {
+static void signal_handler(int signal_num);
+
+static void block_signals(sigset_t* oldset) {
+    sigset_t blockset;
+
+    sigemptyset(&blockset);
+    sigaddset(&blockset, SIGINT);
+    sigaddset(&blockset, SIGQUIT);
+    sigaddset(&blockset, SIGHUP);
+    pthread_sigmask(SIG_BLOCK, &blockset, oldset);
+}
+
+static void unblock_signals(sigset_t* oldset) {
+    pthread_sigmask(SIG_SETMASK, oldset, nullptr);
+}
+
+static void setup_signal_handlers(pid_t pid) {
+    struct sigaction handler = {.sa_handler = signal_handler};
+
+    child_pid = pid;
+    sigaction(SIGINT, &handler, &old_int);
+    sigaction(SIGQUIT, &handler, &old_quit);
+    sigaction(SIGHUP, &handler, &old_hup);
+}
+
+static void restore_signal_handlers() {
+    sigaction(SIGINT, &old_int, nullptr);
+    sigaction(SIGQUIT, &old_quit, nullptr);
+    sigaction(SIGHUP, &old_hup, nullptr);
+    child_pid = 0;
+}
+
+static void signal_handler(int signal_num) {
+    if (child_pid == 0 || kill(child_pid, signal_num) != 0) {
+        restore_signal_handlers();
+        raise(signal_num);
+    }
+}
+
+static int parent(const char* tag, int parent_read, pid_t pid, int* chld_sts, int log_target,
+                  bool abbreviated, const char* file_path, bool forward_signals) {
     int status = 0;
     char buffer[4096];
     struct pollfd poll_fds[] = {
-        [0] = {
-            .fd = parent_read,
-            .events = POLLIN,
-        },
+            {
+                    .fd = parent_read,
+                    .events = POLLIN,
+            },
     };
     int rc = 0;
     int fd;
@@ -308,11 +344,16 @@
     int b = 0;  // end index of unprocessed data
     int sz;
     bool found_child = false;
+    // There is a very small chance that opening child_ptty in the child will fail, but in this case
+    // POLLHUP will not be generated below.  Therefore, we use a 1 second timeout for poll() until
+    // we receive a message from child_ptty.  If this times out, we call waitpid() with WNOHANG to
+    // check the status of the child process and exit appropriately if it has terminated.
+    bool received_messages = false;
     char tmpbuf[256];
 
     log_info.btag = basename(tag);
     if (!log_info.btag) {
-        log_info.btag = (char*) tag;
+        log_info.btag = tag;
     }
 
     if (abbreviated && (log_target == LOG_NONE)) {
@@ -323,8 +364,8 @@
     }
 
     if (log_target & LOG_KLOG) {
-        snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt),
-                 "<6>%.*s: %%s\n", MAX_KLOG_TAG, log_info.btag);
+        snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt), "<6>%.*s: %%s\n", MAX_KLOG_TAG,
+                 log_info.btag);
     }
 
     if ((log_target & LOG_FILE) && !file_path) {
@@ -347,15 +388,16 @@
     log_info.abbreviated = abbreviated;
 
     while (!found_child) {
-        if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
+        int timeout = received_messages ? -1 : 1000;
+        if (TEMP_FAILURE_RETRY(poll(poll_fds, arraysize(poll_fds), timeout)) < 0) {
             ERROR("poll failed\n");
             rc = -1;
             goto err_poll;
         }
 
         if (poll_fds[0].revents & POLLIN) {
-            sz = TEMP_FAILURE_RETRY(
-                read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
+            received_messages = true;
+            sz = TEMP_FAILURE_RETRY(read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
 
             sz += b;
             // Log one line at a time
@@ -396,10 +438,20 @@
             }
         }
 
-        if (poll_fds[0].revents & POLLHUP) {
+        if (!received_messages || (poll_fds[0].revents & POLLHUP)) {
             int ret;
+            sigset_t oldset;
 
-            ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+            if (forward_signals) {
+                // Our signal handlers forward these signals to 'child_pid', but waitpid() may reap
+                // the child, so we must block these signals until we either 1) conclude that the
+                // child is still running or 2) determine the child has been reaped and we have
+                // reset the signals to their original disposition.
+                block_signals(&oldset);
+            }
+
+            int flags = (poll_fds[0].revents & POLLHUP) ? 0 : WNOHANG;
+            ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, flags));
             if (ret < 0) {
                 rc = errno;
                 ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
@@ -408,22 +460,29 @@
             if (ret > 0) {
                 found_child = true;
             }
+
+            if (forward_signals) {
+                if (found_child) {
+                    restore_signal_handlers();
+                }
+                unblock_signals(&oldset);
+            }
         }
     }
 
-    if (chld_sts != NULL) {
+    if (chld_sts != nullptr) {
         *chld_sts = status;
     } else {
-      if (WIFEXITED(status))
-        rc = WEXITSTATUS(status);
-      else
-        rc = -ECHILD;
+        if (WIFEXITED(status))
+            rc = WEXITSTATUS(status);
+        else
+            rc = -ECHILD;
     }
 
     // Flush remaining data
     if (a != b) {
-      buffer[b] = '\0';
-      log_line(&log_info, &buffer[a], b - a);
+        buffer[b] = '\0';
+        log_line(&log_info, &buffer[a], b - a);
     }
 
     /* All the output has been processed, time to dump the abbreviated output */
@@ -432,21 +491,21 @@
     }
 
     if (WIFEXITED(status)) {
-      if (WEXITSTATUS(status)) {
-        snprintf(tmpbuf, sizeof(tmpbuf),
-                 "%s terminated by exit(%d)\n", log_info.btag, WEXITSTATUS(status));
-        do_log_line(&log_info, tmpbuf);
-      }
+        if (WEXITSTATUS(status)) {
+            snprintf(tmpbuf, sizeof(tmpbuf), "%s terminated by exit(%d)\n", log_info.btag,
+                     WEXITSTATUS(status));
+            do_log_line(&log_info, tmpbuf);
+        }
     } else {
-      if (WIFSIGNALED(status)) {
-        snprintf(tmpbuf, sizeof(tmpbuf),
-                       "%s terminated by signal %d\n", log_info.btag, WTERMSIG(status));
-        do_log_line(&log_info, tmpbuf);
-      } else if (WIFSTOPPED(status)) {
-        snprintf(tmpbuf, sizeof(tmpbuf),
-                       "%s stopped by signal %d\n", log_info.btag, WSTOPSIG(status));
-        do_log_line(&log_info, tmpbuf);
-      }
+        if (WIFSIGNALED(status)) {
+            snprintf(tmpbuf, sizeof(tmpbuf), "%s terminated by signal %d\n", log_info.btag,
+                     WTERMSIG(status));
+            do_log_line(&log_info, tmpbuf);
+        } else if (WIFSTOPPED(status)) {
+            snprintf(tmpbuf, sizeof(tmpbuf), "%s stopped by signal %d\n", log_info.btag,
+                     WSTOPSIG(status));
+            do_log_line(&log_info, tmpbuf);
+        }
     }
 
 err_waitpid:
@@ -460,33 +519,24 @@
     return rc;
 }
 
-static void child(int argc, char* argv[]) {
+static void child(int argc, const char* const* argv) {
     // create null terminated argv_child array
     char* argv_child[argc + 1];
-    memcpy(argv_child, argv, argc * sizeof(char *));
-    argv_child[argc] = NULL;
+    memcpy(argv_child, argv, argc * sizeof(char*));
+    argv_child[argc] = nullptr;
 
     if (execvp(argv_child[0], argv_child)) {
-        FATAL_CHILD("executing %s failed: %s\n", argv_child[0],
-                strerror(errno));
+        FATAL_CHILD("executing %s failed: %s\n", argv_child[0], strerror(errno));
     }
 }
 
-int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int_quit,
-        int log_target, bool abbreviated, char *file_path,
-        void *unused_opts, int unused_opts_len) {
+int logwrap_fork_execvp(int argc, const char* const* argv, int* status, bool forward_signals,
+                        int log_target, bool abbreviated, const char* file_path) {
     pid_t pid;
     int parent_ptty;
-    int child_ptty;
-    struct sigaction intact;
-    struct sigaction quitact;
-    sigset_t blockset;
     sigset_t oldset;
     int rc = 0;
 
-    LOG_ALWAYS_FATAL_IF(unused_opts != NULL);
-    LOG_ALWAYS_FATAL_IF(unused_opts_len != 0);
-
     rc = pthread_mutex_lock(&fd_mutex);
     if (rc) {
         ERROR("failed to lock signal_fd mutex\n");
@@ -494,7 +544,7 @@
     }
 
     /* Use ptty instead of socketpair so that STDOUT is not buffered */
-    parent_ptty = TEMP_FAILURE_RETRY(open("/dev/ptmx", O_RDWR));
+    parent_ptty = TEMP_FAILURE_RETRY(posix_openpt(O_RDWR | O_CLOEXEC));
     if (parent_ptty < 0) {
         ERROR("Cannot create parent ptty\n");
         rc = -1;
@@ -503,33 +553,34 @@
 
     char child_devname[64];
     if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
-            ptsname_r(parent_ptty, child_devname, sizeof(child_devname)) != 0) {
+        ptsname_r(parent_ptty, child_devname, sizeof(child_devname)) != 0) {
         ERROR("Problem with /dev/ptmx\n");
         rc = -1;
         goto err_ptty;
     }
 
-    child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR));
-    if (child_ptty < 0) {
-        ERROR("Cannot open child_ptty\n");
-        rc = -1;
-        goto err_child_ptty;
+    if (forward_signals) {
+        // Block these signals until we have the child pid and our signal handlers set up.
+        block_signals(&oldset);
     }
 
-    sigemptyset(&blockset);
-    sigaddset(&blockset, SIGINT);
-    sigaddset(&blockset, SIGQUIT);
-    pthread_sigmask(SIG_BLOCK, &blockset, &oldset);
-
     pid = fork();
     if (pid < 0) {
-        close(child_ptty);
         ERROR("Failed to fork\n");
         rc = -1;
         goto err_fork;
     } else if (pid == 0) {
         pthread_mutex_unlock(&fd_mutex);
-        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+        if (forward_signals) {
+            unblock_signals(&oldset);
+        }
+
+        setsid();
+
+        int child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR | O_CLOEXEC));
+        if (child_ptty < 0) {
+            FATAL_CHILD("Cannot open child_ptty: %s\n", strerror(errno));
+        }
         close(parent_ptty);
 
         dup2(child_ptty, 1);
@@ -538,27 +589,23 @@
 
         child(argc, argv);
     } else {
-        close(child_ptty);
-        if (ignore_int_quit) {
-            struct sigaction ignact;
-
-            memset(&ignact, 0, sizeof(ignact));
-            ignact.sa_handler = SIG_IGN;
-            sigaction(SIGINT, &ignact, &intact);
-            sigaction(SIGQUIT, &ignact, &quitact);
+        if (forward_signals) {
+            setup_signal_handlers(pid);
+            unblock_signals(&oldset);
         }
 
-        rc = parent(argv[0], parent_ptty, pid, status, log_target,
-                    abbreviated, file_path);
+        rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated, file_path,
+                    forward_signals);
+
+        if (forward_signals) {
+            restore_signal_handlers();
+        }
     }
 
-    if (ignore_int_quit) {
-        sigaction(SIGINT, &intact, NULL);
-        sigaction(SIGQUIT, &quitact, NULL);
-    }
 err_fork:
-    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
-err_child_ptty:
+    if (forward_signals) {
+        unblock_signals(&oldset);
+    }
 err_ptty:
     close(parent_ptty);
 err_open:
diff --git a/logwrapper/android_fork_execvp_ext_benchmark.cpp b/logwrapper/logwrap_fork_execvp_benchmark.cpp
similarity index 81%
rename from logwrapper/android_fork_execvp_ext_benchmark.cpp
rename to logwrapper/logwrap_fork_execvp_benchmark.cpp
index 1abd932..b2d0c71 100644
--- a/logwrapper/android_fork_execvp_ext_benchmark.cpp
+++ b/logwrapper/logwrap_fork_execvp_benchmark.cpp
@@ -23,9 +23,7 @@
     const char* argv[] = {"/system/bin/echo", "hello", "world"};
     const int argc = 3;
     while (state.KeepRunning()) {
-        int rc = android_fork_execvp_ext(
-            argc, (char**)argv, NULL /* status */, false /* ignore_int_quit */, LOG_NONE,
-            false /* abbreviated */, NULL /* file_path */, NULL /* opts */, 0 /* opts_len */);
+        int rc = logwrap_fork_execvp(argc, argv, nullptr, false, LOG_NONE, false, nullptr);
         CHECK_EQ(0, rc);
     }
 }
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.cpp
similarity index 62%
rename from logwrapper/logwrapper.c
rename to logwrapper/logwrapper.cpp
index 33454c6..7118d12 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.cpp
@@ -24,27 +24,26 @@
 #include <log/log.h>
 #include <logwrap/logwrap.h>
 
-void fatal(const char *msg) {
+void fatal(const char* msg) {
     fprintf(stderr, "%s", msg);
     ALOG(LOG_ERROR, "logwrapper", "%s", msg);
     exit(-1);
 }
 
 void usage() {
-    fatal(
-        "Usage: logwrapper [-a] [-d] [-k] BINARY [ARGS ...]\n"
-        "\n"
-        "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
-        "the Android logging system. Tag is set to BINARY, priority is\n"
-        "always LOG_INFO.\n"
-        "\n"
-        "-a: Causes logwrapper to do abbreviated logging.\n"
-        "    This logs up to the first 4K and last 4K of the command\n"
-        "    being run, and logs the output when the command exits\n"
-        "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n"
-        "    fault address is set to the status of wait()\n"
-        "-k: Causes logwrapper to log to the kernel log instead of\n"
-        "    the Android system log\n");
+    fatal("Usage: logwrapper [-a] [-d] [-k] BINARY [ARGS ...]\n"
+          "\n"
+          "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
+          "the Android logging system. Tag is set to BINARY, priority is\n"
+          "always LOG_INFO.\n"
+          "\n"
+          "-a: Causes logwrapper to do abbreviated logging.\n"
+          "    This logs up to the first 4K and last 4K of the command\n"
+          "    being run, and logs the output when the command exits\n"
+          "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n"
+          "    fault address is set to the status of wait()\n"
+          "-k: Causes logwrapper to log to the kernel log instead of\n"
+          "    the Android system log\n");
 }
 
 int main(int argc, char* argv[]) {
@@ -69,7 +68,7 @@
                 break;
             case '?':
             default:
-              usage();
+                usage();
         }
     }
     argc -= optind;
@@ -79,8 +78,7 @@
         usage();
     }
 
-    rc = android_fork_execvp_ext(argc, &argv[0], &status, true,
-                                 log_target, abbreviated, NULL, NULL, 0);
+    rc = logwrap_fork_execvp(argc, &argv[0], &status, true, log_target, abbreviated, nullptr);
     if (!rc) {
         if (WIFEXITED(status))
             rc = WEXITSTATUS(status);
@@ -89,8 +87,8 @@
     }
 
     if (seg_fault_on_exit) {
-        uintptr_t fault_address = (uintptr_t) status;
-        *(int *) fault_address = 0;  // causes SIGSEGV with fault_address = status
+        uintptr_t fault_address = (uintptr_t)status;
+        *(int*)fault_address = 0;  // causes SIGSEGV with fault_address = status
     }
 
     return rc;
diff --git a/mkbootimg/Android.bp b/mkbootimg/Android.bp
deleted file mode 100644
index c3cf746..0000000
--- a/mkbootimg/Android.bp
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2012 The Android Open Source Project
-
-cc_library_headers {
-    name: "libmkbootimg_abi_headers",
-    vendor_available: true,
-    export_include_dirs: ["include"],
-}
-
-cc_library_headers {
-    name: "bootimg_headers",
-    vendor_available: true,
-    recovery_available: true,
-    export_include_dirs: ["include/bootimg"],
-    host_supported: true,
-    target: {
-        windows: {
-            enabled: true,
-        },
-    },
-}
-
-cc_library {
-    name: "libmkbootimg_abi_check",
-    vendor_available: true,
-    vndk: {
-        enabled: true,
-    },
-    srcs: [
-        "mkbootimg_dummy.cpp",
-    ],
-    header_libs: ["libmkbootimg_abi_headers"],
-    export_header_lib_headers: ["libmkbootimg_abi_headers"],
-}
-
-python_defaults {
-    name: "mkbootimg_defaults",
-
-    version: {
-        py2: {
-            enabled: true,
-            embedded_launcher: true,
-        },
-        py3: {
-            enabled: false,
-            embedded_launcher: false,
-        },
-    },
-}
-
-python_binary_host {
-    name: "mkbootimg",
-    defaults: ["mkbootimg_defaults"],
-    srcs: [
-        "mkbootimg.py",
-    ],
-}
-
-python_binary_host {
-    name: "unpack_bootimg",
-    defaults: ["mkbootimg_defaults"],
-    srcs: [
-        "unpack_bootimg.py",
-    ],
-}
diff --git a/mkbootimg/OWNERS b/mkbootimg/OWNERS
deleted file mode 100644
index 3a00860..0000000
--- a/mkbootimg/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-hridya@google.com
-tbao@google.com
diff --git a/mkbootimg/include/abi_check/mkbootimg_abi_check.h b/mkbootimg/include/abi_check/mkbootimg_abi_check.h
deleted file mode 100644
index d478aba..0000000
--- a/mkbootimg/include/abi_check/mkbootimg_abi_check.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.
- */
-
-#include <bootimg/bootimg.h>
-
-// This header has been created for the following reaons:
-//    1) In order for a change in a user defined type to be classified as API /
-//       ABI breaking, it needs to be referenced by an 'exported interface'
-//       (in this case the function mkbootimg_dummy).
-//    2) Since 'mkbootimg_dummy' needs to be exported, we need to have it
-//       exposed through a public header.
-//    3) It is desirable not to pollute bootimg.h with interfaces which are not
-//       'used' in reality by on device binaries. Furthermore, bootimg.h might
-//       be exported by a library in the future, so we must avoid polluting it.
-void mkbootimg_dummy(boot_img_hdr*);
diff --git a/mkbootimg/include/bootimg/bootimg.h b/mkbootimg/include/bootimg/bootimg.h
deleted file mode 100644
index 9ee7869..0000000
--- a/mkbootimg/include/bootimg/bootimg.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2007 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 <stdint.h>
-
-#define BOOT_MAGIC "ANDROID!"
-#define BOOT_MAGIC_SIZE 8
-#define BOOT_NAME_SIZE 16
-#define BOOT_ARGS_SIZE 512
-#define BOOT_EXTRA_ARGS_SIZE 1024
-
-// The bootloader expects the structure of boot_img_hdr with header
-// version 0 to be as follows:
-struct boot_img_hdr_v0 {
-    // Must be BOOT_MAGIC.
-    uint8_t magic[BOOT_MAGIC_SIZE];
-
-    uint32_t kernel_size; /* size in bytes */
-    uint32_t kernel_addr; /* physical load addr */
-
-    uint32_t ramdisk_size; /* size in bytes */
-    uint32_t ramdisk_addr; /* physical load addr */
-
-    uint32_t second_size; /* size in bytes */
-    uint32_t second_addr; /* physical load addr */
-
-    uint32_t tags_addr; /* physical addr for kernel tags */
-    uint32_t page_size; /* flash page size we assume */
-
-    // Version of the boot image header.
-    uint32_t header_version;
-
-    // Operating system version and security patch level.
-    // For version "A.B.C" and patch level "Y-M-D":
-    //   (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
-    //   os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
-    uint32_t os_version;
-
-#if __cplusplus
-    void SetOsVersion(unsigned major, unsigned minor, unsigned patch) {
-        os_version &= ((1 << 11) - 1);
-        os_version |= (((major & 0x7f) << 25) | ((minor & 0x7f) << 18) | ((patch & 0x7f) << 11));
-    }
-
-    void SetOsPatchLevel(unsigned year, unsigned month) {
-        os_version &= ~((1 << 11) - 1);
-        os_version |= (((year - 2000) & 0x7f) << 4) | ((month & 0xf) << 0);
-    }
-#endif
-
-    uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
-
-    uint8_t cmdline[BOOT_ARGS_SIZE];
-
-    uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
-
-    // Supplemental command line data; kept here to maintain
-    // binary compatibility with older versions of mkbootimg.
-    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
-} __attribute__((packed));
-
-/*
- * It is expected that callers would explicitly specify which version of the
- * boot image header they need to use.
- */
-typedef struct boot_img_hdr_v0 boot_img_hdr;
-
-/* When a boot header is of version 0, the structure of boot image is as
- * follows:
- *
- * +-----------------+
- * | boot header     | 1 page
- * +-----------------+
- * | kernel          | n pages
- * +-----------------+
- * | ramdisk         | m pages
- * +-----------------+
- * | second stage    | o pages
- * +-----------------+
- *
- * n = (kernel_size + page_size - 1) / page_size
- * m = (ramdisk_size + page_size - 1) / page_size
- * o = (second_size + page_size - 1) / page_size
- *
- * 0. all entities are page_size aligned in flash
- * 1. kernel and ramdisk are required (size != 0)
- * 2. second is optional (second_size == 0 -> no second)
- * 3. load each element (kernel, ramdisk, second) at
- *    the specified physical address (kernel_addr, etc)
- * 4. prepare tags at tag_addr.  kernel_args[] is
- *    appended to the kernel commandline in the tags.
- * 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
- * 6. if second_size != 0: jump to second_addr
- *    else: jump to kernel_addr
- */
-
-struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
-    uint32_t recovery_dtbo_size;   /* size in bytes for recovery DTBO/ACPIO image */
-    uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */
-    uint32_t header_size;
-} __attribute__((packed));
-
-/* When the boot image header has a version of 2, the structure of the boot
- * image is as follows:
- *
- * +---------------------+
- * | boot header         | 1 page
- * +---------------------+
- * | kernel              | n pages
- * +---------------------+
- * | ramdisk             | m pages
- * +---------------------+
- * | second stage        | o pages
- * +---------------------+
- * | recovery dtbo/acpio | p pages
- * +---------------------+
- * | dtb                 | q pages
- * +---------------------+
-
- * n = (kernel_size + page_size - 1) / page_size
- * m = (ramdisk_size + page_size - 1) / page_size
- * o = (second_size + page_size - 1) / page_size
- * p = (recovery_dtbo_size + page_size - 1) / page_size
- * q = (dtb_size + page_size - 1) / page_size
- *
- * 0. all entities are page_size aligned in flash
- * 1. kernel, ramdisk and DTB are required (size != 0)
- * 2. recovery_dtbo/recovery_acpio is required for recovery.img in non-A/B
- *    devices(recovery_dtbo_size != 0)
- * 3. second is optional (second_size == 0 -> no second)
- * 4. load each element (kernel, ramdisk, second, dtb) at
- *    the specified physical address (kernel_addr, etc)
- * 5. If booting to recovery mode in a non-A/B device, extract recovery
- *    dtbo/acpio and apply the correct set of overlays on the base device tree
- *    depending on the hardware/product revision.
- * 6. prepare tags at tag_addr.  kernel_args[] is
- *    appended to the kernel commandline in the tags.
- * 7. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
- * 8. if second_size != 0: jump to second_addr
- *    else: jump to kernel_addr
- */
-struct boot_img_hdr_v2 : public boot_img_hdr_v1 {
-    uint32_t dtb_size; /* size in bytes for DTB image */
-    uint64_t dtb_addr; /* physical load address for DTB image */
-} __attribute__((packed));
diff --git a/mkbootimg/mkbootimg.py b/mkbootimg/mkbootimg.py
deleted file mode 100644
index 92b11a5..0000000
--- a/mkbootimg/mkbootimg.py
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015, 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.
-
-from __future__ import print_function
-from sys import argv, exit, stderr
-from argparse import ArgumentParser, FileType, Action
-from os import fstat
-from struct import pack
-from hashlib import sha1
-import sys
-import re
-
-def filesize(f):
-    if f is None:
-        return 0
-    try:
-        return fstat(f.fileno()).st_size
-    except OSError:
-        return 0
-
-
-def update_sha(sha, f):
-    if f:
-        sha.update(f.read())
-        f.seek(0)
-        sha.update(pack('I', filesize(f)))
-    else:
-        sha.update(pack('I', 0))
-
-
-def pad_file(f, padding):
-    pad = (padding - (f.tell() & (padding - 1))) & (padding - 1)
-    f.write(pack(str(pad) + 'x'))
-
-
-def get_number_of_pages(image_size, page_size):
-    """calculates the number of pages required for the image"""
-    return (image_size + page_size - 1) / page_size
-
-
-def get_recovery_dtbo_offset(args):
-    """calculates the offset of recovery_dtbo image in the boot image"""
-    num_header_pages = 1 # header occupies a page
-    num_kernel_pages = get_number_of_pages(filesize(args.kernel), args.pagesize)
-    num_ramdisk_pages = get_number_of_pages(filesize(args.ramdisk), args.pagesize)
-    num_second_pages = get_number_of_pages(filesize(args.second), args.pagesize)
-    dtbo_offset = args.pagesize * (num_header_pages + num_kernel_pages +
-                                   num_ramdisk_pages + num_second_pages)
-    return dtbo_offset
-
-
-def write_header(args):
-    BOOT_IMAGE_HEADER_V1_SIZE = 1648
-    BOOT_IMAGE_HEADER_V2_SIZE = 1660
-    BOOT_MAGIC = 'ANDROID!'.encode()
-
-    if (args.header_version > 2):
-        raise ValueError('Boot header version %d not supported' % args.header_version)
-
-    args.output.write(pack('8s', BOOT_MAGIC))
-    args.output.write(pack('10I',
-        filesize(args.kernel),                          # size in bytes
-        args.base + args.kernel_offset,                 # physical load addr
-        filesize(args.ramdisk),                         # size in bytes
-        args.base + args.ramdisk_offset,                # physical load addr
-        filesize(args.second),                          # size in bytes
-        args.base + args.second_offset,                 # physical load addr
-        args.base + args.tags_offset,                   # physical addr for kernel tags
-        args.pagesize,                                  # flash page size we assume
-        args.header_version,                            # version of bootimage header
-        (args.os_version << 11) | args.os_patch_level)) # os version and patch level
-    args.output.write(pack('16s', args.board.encode())) # asciiz product name
-    args.output.write(pack('512s', args.cmdline[:512].encode()))
-
-    sha = sha1()
-    update_sha(sha, args.kernel)
-    update_sha(sha, args.ramdisk)
-    update_sha(sha, args.second)
-
-    if args.header_version > 0:
-        update_sha(sha, args.recovery_dtbo)
-    if args.header_version > 1:
-        update_sha(sha, args.dtb)
-
-    img_id = pack('32s', sha.digest())
-
-    args.output.write(img_id)
-    args.output.write(pack('1024s', args.cmdline[512:].encode()))
-
-    if args.header_version > 0:
-        args.output.write(pack('I', filesize(args.recovery_dtbo)))   # size in bytes
-        if args.recovery_dtbo:
-            args.output.write(pack('Q', get_recovery_dtbo_offset(args))) # recovery dtbo offset
-        else:
-            args.output.write(pack('Q', 0)) # Will be set to 0 for devices without a recovery dtbo
-
-    # Populate boot image header size for header versions 1 and 2.
-    if args.header_version == 1:
-        args.output.write(pack('I', BOOT_IMAGE_HEADER_V1_SIZE))
-    elif args.header_version == 2:
-        args.output.write(pack('I', BOOT_IMAGE_HEADER_V2_SIZE))
-
-    if args.header_version > 1:
-        args.output.write(pack('I', filesize(args.dtb)))   # size in bytes
-        args.output.write(pack('Q', args.base + args.dtb_offset)) # dtb physical load address
-    pad_file(args.output, args.pagesize)
-    return img_id
-
-
-class ValidateStrLenAction(Action):
-    def __init__(self, option_strings, dest, nargs=None, **kwargs):
-        if 'maxlen' not in kwargs:
-            raise ValueError('maxlen must be set')
-        self.maxlen = int(kwargs['maxlen'])
-        del kwargs['maxlen']
-        super(ValidateStrLenAction, self).__init__(option_strings, dest, **kwargs)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        if len(values) > self.maxlen:
-            raise ValueError('String argument too long: max {0:d}, got {1:d}'.
-                format(self.maxlen, len(values)))
-        setattr(namespace, self.dest, values)
-
-
-def write_padded_file(f_out, f_in, padding):
-    if f_in is None:
-        return
-    f_out.write(f_in.read())
-    pad_file(f_out, padding)
-
-
-def parse_int(x):
-    return int(x, 0)
-
-def parse_os_version(x):
-    match = re.search(r'^(\d{1,3})(?:\.(\d{1,3})(?:\.(\d{1,3}))?)?', x)
-    if match:
-        a = int(match.group(1))
-        b = c = 0
-        if match.lastindex >= 2:
-            b = int(match.group(2))
-        if match.lastindex == 3:
-            c = int(match.group(3))
-        # 7 bits allocated for each field
-        assert a < 128
-        assert b < 128
-        assert c < 128
-        return (a << 14) | (b << 7) | c
-    return 0
-
-def parse_os_patch_level(x):
-    match = re.search(r'^(\d{4})-(\d{2})-(\d{2})', x)
-    if match:
-        y = int(match.group(1)) - 2000
-        m = int(match.group(2))
-        # 7 bits allocated for the year, 4 bits for the month
-        assert y >= 0 and y < 128
-        assert m > 0 and m <= 12
-        return (y << 4) | m
-    return 0
-
-def parse_cmdline():
-    parser = ArgumentParser()
-    parser.add_argument('--kernel', help='path to the kernel', type=FileType('rb'),
-                        required=True)
-    parser.add_argument('--ramdisk', help='path to the ramdisk', type=FileType('rb'))
-    parser.add_argument('--second', help='path to the 2nd bootloader', type=FileType('rb'))
-    parser.add_argument('--dtb', help='path to dtb', type=FileType('rb'))
-    recovery_dtbo_group = parser.add_mutually_exclusive_group()
-    recovery_dtbo_group.add_argument('--recovery_dtbo', help='path to the recovery DTBO', type=FileType('rb'))
-    recovery_dtbo_group.add_argument('--recovery_acpio', help='path to the recovery ACPIO',
-                                     type=FileType('rb'), metavar='RECOVERY_ACPIO', dest='recovery_dtbo')
-    parser.add_argument('--cmdline', help='extra arguments to be passed on the '
-                        'kernel command line', default='', action=ValidateStrLenAction, maxlen=1536)
-    parser.add_argument('--base', help='base address', type=parse_int, default=0x10000000)
-    parser.add_argument('--kernel_offset', help='kernel offset', type=parse_int, default=0x00008000)
-    parser.add_argument('--ramdisk_offset', help='ramdisk offset', type=parse_int, default=0x01000000)
-    parser.add_argument('--second_offset', help='2nd bootloader offset', type=parse_int,
-                        default=0x00f00000)
-    parser.add_argument('--dtb_offset', help='dtb offset', type=parse_int, default=0x01f00000)
-
-    parser.add_argument('--os_version', help='operating system version', type=parse_os_version,
-                        default=0)
-    parser.add_argument('--os_patch_level', help='operating system patch level',
-                        type=parse_os_patch_level, default=0)
-    parser.add_argument('--tags_offset', help='tags offset', type=parse_int, default=0x00000100)
-    parser.add_argument('--board', help='board name', default='', action=ValidateStrLenAction,
-                        maxlen=16)
-    parser.add_argument('--pagesize', help='page size', type=parse_int,
-                        choices=[2**i for i in range(11,15)], default=2048)
-    parser.add_argument('--id', help='print the image ID on standard output',
-                        action='store_true')
-    parser.add_argument('--header_version', help='boot image header version', type=parse_int, default=0)
-    parser.add_argument('-o', '--output', help='output file name', type=FileType('wb'),
-                        required=True)
-    return parser.parse_args()
-
-
-def write_data(args):
-    write_padded_file(args.output, args.kernel, args.pagesize)
-    write_padded_file(args.output, args.ramdisk, args.pagesize)
-    write_padded_file(args.output, args.second, args.pagesize)
-
-    if args.header_version > 0:
-        write_padded_file(args.output, args.recovery_dtbo, args.pagesize)
-    if args.header_version > 1:
-        write_padded_file(args.output, args.dtb, args.pagesize)
-
-def main():
-    args = parse_cmdline()
-    img_id = write_header(args)
-    write_data(args)
-    if args.id:
-        if isinstance(img_id, str):
-            # Python 2's struct.pack returns a string, but py3 returns bytes.
-            img_id = [ord(x) for x in img_id]
-        print('0x' + ''.join('{:02x}'.format(c) for c in img_id))
-
-if __name__ == '__main__':
-    main()
diff --git a/mkbootimg/unpack_bootimg.py b/mkbootimg/unpack_bootimg.py
deleted file mode 100755
index 789bf5e..0000000
--- a/mkbootimg/unpack_bootimg.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/env python
-# Copyright 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.
-
-"""unpacks the bootimage.
-
-Extracts the kernel, ramdisk, second bootloader, dtb and recovery dtbo images.
-"""
-
-from __future__ import print_function
-from argparse import ArgumentParser, FileType
-from struct import unpack
-import os
-
-
-def create_out_dir(dir_path):
-    """creates a directory 'dir_path' if it does not exist"""
-    if not os.path.exists(dir_path):
-        os.makedirs(dir_path)
-
-
-def extract_image(offset, size, bootimage, extracted_image_name):
-    """extracts an image from the bootimage"""
-    bootimage.seek(offset)
-    with open(extracted_image_name, 'wb') as file_out:
-        file_out.write(bootimage.read(size))
-
-
-def get_number_of_pages(image_size, page_size):
-    """calculates the number of pages required for the image"""
-    return (image_size + page_size - 1) / page_size
-
-
-def unpack_bootimage(args):
-    """extracts kernel, ramdisk, second bootloader and recovery dtbo"""
-    boot_magic = unpack('8s', args.boot_img.read(8))
-    print('boot_magic: %s' % boot_magic)
-    kernel_ramdisk_second_info = unpack('10I', args.boot_img.read(10 * 4))
-    print('kernel_size: %s' % kernel_ramdisk_second_info[0])
-    print('kernel load address: %#x' % kernel_ramdisk_second_info[1])
-    print('ramdisk size: %s' % kernel_ramdisk_second_info[2])
-    print('ramdisk load address: %#x' % kernel_ramdisk_second_info[3])
-    print('second bootloader size: %s' % kernel_ramdisk_second_info[4])
-    print('second bootloader load address: %#x' % kernel_ramdisk_second_info[5])
-    print('kernel tags load address: %#x' % kernel_ramdisk_second_info[6])
-    print('page size: %s' % kernel_ramdisk_second_info[7])
-    print('boot image header version: %s' % kernel_ramdisk_second_info[8])
-    print('os version and patch level: %s' % kernel_ramdisk_second_info[9])
-
-    product_name = unpack('16s', args.boot_img.read(16))
-    print('product name: %s' % product_name)
-    cmdline = unpack('512s', args.boot_img.read(512))
-    print('command line args: %s' % cmdline)
-
-    args.boot_img.read(32)  # ignore SHA
-
-    extra_cmdline = unpack('1024s', args.boot_img.read(1024))
-    print('additional command line args: %s' % extra_cmdline)
-
-    kernel_size = kernel_ramdisk_second_info[0]
-    ramdisk_size = kernel_ramdisk_second_info[2]
-    second_size = kernel_ramdisk_second_info[4]
-    page_size = kernel_ramdisk_second_info[7]
-    version = kernel_ramdisk_second_info[8]
-    if version > 0:
-        recovery_dtbo_size = unpack('I', args.boot_img.read(1 * 4))[0]
-        print('recovery dtbo size: %s' % recovery_dtbo_size)
-        recovery_dtbo_offset = unpack('Q', args.boot_img.read(8))[0]
-        print('recovery dtbo offset: %#x' % recovery_dtbo_offset)
-        boot_header_size = unpack('I', args.boot_img.read(4))[0]
-        print('boot header size: %s' % boot_header_size)
-    else:
-        recovery_dtbo_size = 0
-    if version > 1:
-        dtb_size = unpack('I', args.boot_img.read(4))[0]
-        print('dtb size: %s' % dtb_size)
-        dtb_load_address = unpack('Q', args.boot_img.read(8))[0]
-        print('dtb address: %#x' % dtb_load_address)
-    else:
-        dtb_size = 0
-
-
-    # The first page contains the boot header
-    num_header_pages = 1
-
-    num_kernel_pages = get_number_of_pages(kernel_size, page_size)
-    kernel_offset = page_size * num_header_pages  # header occupies a page
-    image_info_list = [(kernel_offset, kernel_size, 'kernel')]
-
-    num_ramdisk_pages = get_number_of_pages(ramdisk_size, page_size)
-    ramdisk_offset = page_size * (num_header_pages + num_kernel_pages
-                                 ) # header + kernel
-    image_info_list.append((ramdisk_offset, ramdisk_size, 'ramdisk'))
-
-    if second_size > 0:
-        second_offset = page_size * (
-                num_header_pages + num_kernel_pages + num_ramdisk_pages
-                )  # header + kernel + ramdisk
-        image_info_list.append((second_offset, second_size, 'second'))
-
-    if recovery_dtbo_size > 0:
-        image_info_list.append((recovery_dtbo_offset, recovery_dtbo_size,
-                                'recovery_dtbo'))
-    if dtb_size > 0:
-        num_second_pages = get_number_of_pages(second_size, page_size)
-        num_recovery_dtbo_pages = get_number_of_pages(recovery_dtbo_size, page_size)
-        dtb_offset = page_size * (
-            num_header_pages + num_kernel_pages + num_ramdisk_pages + num_second_pages +
-            num_recovery_dtbo_pages
-        )
-
-        image_info_list.append((dtb_offset, dtb_size, 'dtb'))
-
-    for image_info in image_info_list:
-        extract_image(image_info[0], image_info[1], args.boot_img,
-                      os.path.join(args.out, image_info[2]))
-
-
-def parse_cmdline():
-    """parse command line arguments"""
-    parser = ArgumentParser(
-        description='Unpacks boot.img/recovery.img, extracts the kernel,'
-        'ramdisk, second bootloader, recovery dtbo and dtb')
-    parser.add_argument(
-        '--boot_img',
-        help='path to boot image',
-        type=FileType('rb'),
-        required=True)
-    parser.add_argument('--out', help='path to out binaries', default='out')
-    return parser.parse_args()
-
-
-def main():
-    """parse arguments and unpack boot image"""
-    args = parse_cmdline()
-    create_out_dir(args.out)
-    unpack_bootimage(args)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 5c57d69..ac802b5 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -3,6 +3,7 @@
     host_supported: true,
     vendor_available: true,
     recovery_available: true,
+    native_bridge_supported: true,
     srcs: ["property_info_parser.cpp"],
 
     cpp_std: "experimental",
diff --git a/property_service/libpropertyinfoserializer/Android.bp b/property_service/libpropertyinfoserializer/Android.bp
index 51c1226..aa02a3a 100644
--- a/property_service/libpropertyinfoserializer/Android.bp
+++ b/property_service/libpropertyinfoserializer/Android.bp
@@ -1,7 +1,6 @@
 cc_defaults {
     name: "propertyinfoserializer_defaults",
     host_supported: true,
-    vendor_available: true,
     cpp_std: "experimental",
     cppflags: [
         "-Wall",
@@ -9,8 +8,8 @@
         "-Werror",
     ],
     static_libs: [
-        "libpropertyinfoparser",
         "libbase",
+        "libpropertyinfoparser",
     ],
 }
 
diff --git a/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h b/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h
index 439813d..dfb1d11 100644
--- a/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h
+++ b/property_service/libpropertyinfoserializer/include/property_info_serializer/property_info_serializer.h
@@ -14,8 +14,7 @@
 // limitations under the License.
 //
 
-#ifndef PROPERTY_INFO_SERIALIZER_H
-#define PROPERTY_INFO_SERIALIZER_H
+#pragma once
 
 #include <string>
 #include <vector>
@@ -41,11 +40,9 @@
                const std::string& default_context, const std::string& default_type,
                std::string* serialized_trie, std::string* error);
 
-void ParsePropertyInfoFile(const std::string& file_contents,
+void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact,
                            std::vector<PropertyInfoEntry>* property_infos,
                            std::vector<std::string>* errors);
 
 }  // namespace properties
 }  // namespace android
-
-#endif
diff --git a/property_service/libpropertyinfoserializer/property_info_file.cpp b/property_service/libpropertyinfoserializer/property_info_file.cpp
index 2cdc62d..771a9ce 100644
--- a/property_service/libpropertyinfoserializer/property_info_file.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_file.cpp
@@ -56,7 +56,8 @@
   return false;
 }
 
-bool ParsePropertyInfoLine(const std::string& line, PropertyInfoEntry* out, std::string* error) {
+bool ParsePropertyInfoLine(const std::string& line, bool require_prefix_or_exact,
+                           PropertyInfoEntry* out, std::string* error) {
   auto tokenizer = SpaceTokenizer(line);
 
   auto property = tokenizer.GetNext();
@@ -72,7 +73,7 @@
   }
 
   // It is not an error to not find exact_match or a type, as older files will not contain them.
-  auto exact_match = tokenizer.GetNext();
+  auto match_operation = tokenizer.GetNext();
   // We reformat type to be space deliminated regardless of the input whitespace for easier storage
   // and subsequent parsing.
   auto type_strings = std::vector<std::string>{};
@@ -82,18 +83,27 @@
     type = tokenizer.GetNext();
   }
 
+  bool exact_match = false;
+  if (match_operation == "exact") {
+    exact_match = true;
+  } else if (match_operation != "prefix" && match_operation != "" && require_prefix_or_exact) {
+    *error = "Match operation '" + match_operation +
+             "' is not valid: must be either 'prefix' or 'exact'";
+    return false;
+  }
+
   if (!type_strings.empty() && !IsTypeValid(type_strings)) {
     *error = "Type '" + Join(type_strings, " ") + "' is not valid";
     return false;
   }
 
-  *out = {property, context, Join(type_strings, " "), exact_match == "exact"};
+  *out = {property, context, Join(type_strings, " "), exact_match};
   return true;
 }
 
 }  // namespace
 
-void ParsePropertyInfoFile(const std::string& file_contents,
+void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact,
                            std::vector<PropertyInfoEntry>* property_infos,
                            std::vector<std::string>* errors) {
   // Do not clear property_infos to allow this function to be called on multiple files, with
@@ -108,7 +118,8 @@
 
     auto property_info_entry = PropertyInfoEntry{};
     auto parse_error = std::string{};
-    if (!ParsePropertyInfoLine(trimmed_line, &property_info_entry, &parse_error)) {
+    if (!ParsePropertyInfoLine(trimmed_line, require_prefix_or_exact, &property_info_entry,
+                               &parse_error)) {
       errors->emplace_back(parse_error);
       continue;
     }
diff --git a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
index f484550..f4a846f 100644
--- a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
@@ -375,9 +375,11 @@
       {"audio_hal.period_size", "u:object_r:default_prop:s0"},
       {"bluetooth.enable_timeout_ms", "u:object_r:bluetooth_prop:s0"},
       {"dalvik.vm.appimageformat", "u:object_r:dalvik_prop:s0"},
+      {"dalvik.vm.boot-dex2oat-cpu-set", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.boot-dex2oat-threads", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dex2oat-Xms", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dex2oat-Xmx", "u:object_r:dalvik_prop:s0"},
+      {"dalvik.vm.dex2oat-cpu-set", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dex2oat-threads", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.dexopt.secondary", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.heapgrowthlimit", "u:object_r:dalvik_prop:s0"},
@@ -388,6 +390,7 @@
       {"dalvik.vm.heaptargetutilization", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.image-dex2oat-Xms", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.image-dex2oat-Xmx", "u:object_r:dalvik_prop:s0"},
+      {"dalvik.vm.image-dex2oat-cpu-set", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.image-dex2oat-threads", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.isa.arm.features", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.isa.arm.variant", "u:object_r:dalvik_prop:s0"},
@@ -585,6 +588,7 @@
       {"ro.boottime.imsdatadaemon", "u:object_r:boottime_prop:s0"},
       {"ro.boottime.imsqmidaemon", "u:object_r:boottime_prop:s0"},
       {"ro.boottime.init", "u:object_r:boottime_prop:s0"},
+      {"ro.boottime.init.first_stage", "u:object_r:boottime_prop:s0"},
       {"ro.boottime.init.cold_boot_wait", "u:object_r:boottime_prop:s0"},
       {"ro.boottime.init.mount_all.default", "u:object_r:boottime_prop:s0"},
       {"ro.boottime.init.selinux", "u:object_r:boottime_prop:s0"},
diff --git a/property_service/property_info_checker/property_info_checker.cpp b/property_service/property_info_checker/property_info_checker.cpp
index 52c4383..61b368e 100644
--- a/property_service/property_info_checker/property_info_checker.cpp
+++ b/property_service/property_info_checker/property_info_checker.cpp
@@ -153,7 +153,7 @@
     }
 
     auto errors = std::vector<std::string>{};
-    ParsePropertyInfoFile(file_contents, &property_info_entries, &errors);
+    ParsePropertyInfoFile(file_contents, true, &property_info_entries, &errors);
     if (!errors.empty()) {
       for (const auto& error : errors) {
         std::cerr << "Could not read line from '" << filename << "': " << error << std::endl;
diff --git a/reboot/Android.bp b/reboot/Android.bp
index 805fd9a..cc71723 100644
--- a/reboot/Android.bp
+++ b/reboot/Android.bp
@@ -5,4 +5,5 @@
     srcs: ["reboot.c"],
     shared_libs: ["libcutils"],
     cflags: ["-Werror"],
+    recovery_available: true,
 }
diff --git a/libmeminfo/vts/Android.bp b/rootdir/Android.bp
similarity index 68%
rename from libmeminfo/vts/Android.bp
rename to rootdir/Android.bp
index 5a3a23b..96b5e0d 100644
--- a/libmeminfo/vts/Android.bp
+++ b/rootdir/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2019 The Android Open Source Project
+// Copyright 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.
@@ -12,9 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-cc_test {
-    name: "vts_meminfo_test",
-    defaults: ["libmeminfo_defaults"],
-    srcs: ["vts_meminfo_test.cpp"],
-    static_libs: ["libmeminfo"],
+prebuilt_etc {
+    name: "init.rc",
+    src: "init.rc",
+    sub_dir: "init/hw",
+    required: ["fsverity_init"],
+}
+
+prebuilt_etc {
+    name: "ueventd.rc",
+    src: "ueventd.rc",
+    recovery_available: true,
 }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7ff1588..5821379 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -1,22 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
 
 #######################################
-# init.rc
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := init.rc
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
-LOCAL_REQUIRED_MODULES := fsverity_init
-
-# The init symlink must be a post install command of a file that is to TARGET_ROOT_OUT.
-# Since init.rc is required for init and satisfies that requirement, we hijack it to create the symlink.
-LOCAL_POST_INSTALL_CMD := ln -sf /system/bin/init $(TARGET_ROOT_OUT)/init
-
-include $(BUILD_PREBUILT)
-
-#######################################
 # init-debug.rc
 include $(CLEAR_VARS)
 
@@ -58,15 +42,6 @@
 endif
 
 #######################################
-# fsverity_init
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= fsverity_init
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_SRC_FILES := fsverity_init.sh
-include $(BUILD_PREBUILT)
-
-#######################################
 # init.environ.rc
 
 include $(CLEAR_VARS)
@@ -89,7 +64,7 @@
 
 EXPORT_GLOBAL_GCOV_OPTIONS :=
 ifeq ($(NATIVE_COVERAGE),true)
-  EXPORT_GLOBAL_GCOV_OPTIONS := export GCOV_PREFIX /data/misc/gcov
+  EXPORT_GLOBAL_GCOV_OPTIONS := export GCOV_PREFIX /data/misc/trace
 endif
 
 # Put it here instead of in init.rc module definition,
@@ -97,11 +72,12 @@
 #
 # create some directories (some are mount points) and symlinks
 LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
-    sbin dev proc sys system data odm oem acct config storage mnt apex debug_ramdisk $(BOARD_ROOT_EXTRA_FOLDERS)); \
+    dev proc sys system data data_mirror odm oem acct config storage mnt apex debug_ramdisk \
+    linkerconfig $(BOARD_ROOT_EXTRA_FOLDERS)); \
     ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \
     ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
     ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
-    ln -sf /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \
+    ln -sfn /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \
     ln -sf /storage/self/primary $(TARGET_ROOT_OUT)/sdcard
 ifdef BOARD_USES_VENDORIMAGE
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/vendor
@@ -113,10 +89,10 @@
 else
   LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product $(TARGET_ROOT_OUT)/product
 endif
-ifdef BOARD_USES_PRODUCT_SERVICESIMAGE
-  LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/product_services
+ifdef BOARD_USES_SYSTEM_EXTIMAGE
+  LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/system_ext
 else
-  LOCAL_POST_INSTALL_CMD += ; ln -sf /system/product_services $(TARGET_ROOT_OUT)/product_services
+  LOCAL_POST_INSTALL_CMD += ; ln -sf /system/system_ext $(TARGET_ROOT_OUT)/system_ext
 endif
 ifdef BOARD_USES_METADATA_PARTITION
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/metadata
@@ -157,6 +133,10 @@
   LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/postinstall
 endif
 
+# The init symlink must be a post install command of a file that is to TARGET_ROOT_OUT.
+# Since init.environ.rc is required for init and satisfies that requirement, we hijack it to create the symlink.
+LOCAL_POST_INSTALL_CMD += ; ln -sf /system/bin/init $(TARGET_ROOT_OUT)/init
+
 include $(BUILD_SYSTEM)/base_rules.mk
 
 $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in
@@ -176,206 +156,29 @@
 )
 endef
 
-
 #######################################
-# ld.config.txt selection variables
-#
-_enforce_vndk_at_runtime := false
-ifdef BOARD_VNDK_VERSION
-  ifneq ($(BOARD_VNDK_RUNTIME_DISABLE),true)
-    _enforce_vndk_at_runtime := true
-  endif
-endif
-
-_enforce_vndk_lite_at_runtime := false
-ifeq ($(_enforce_vndk_at_runtime),false)
-  ifeq ($(PRODUCT_TREBLE_LINKER_NAMESPACES)|$(SANITIZE_TARGET),true|)
-    _enforce_vndk_lite_at_runtime := true
-  endif
-endif
-
-#######################################
-# ld.config.txt
-#
-# For VNDK enforced devices that have defined BOARD_VNDK_VERSION, use
-# "ld.config.txt" as a source file. This configuration includes strict VNDK
-# run-time restrictions for vendor process.
-#
-# Other treblized devices, that have not defined BOARD_VNDK_VERSION or that
-# have set BOARD_VNDK_RUNTIME_DISABLE to true, use "ld.config.vndk_lite.txt"
-# as a source file. This configuration does not have strict VNDK run-time
-# restrictions.
-#
-# If the device is not treblized, use "ld.config.legacy.txt" for legacy
-# namespace configuration.
-#
+# sanitizer.libraries.txt
 include $(CLEAR_VARS)
-LOCAL_MODULE := ld.config.txt
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-
-# Start of runtime APEX compatibility.
-#
-# Meta-comment:
-# The placing of this section is somewhat arbitrary. The LOCAL_POST_INSTALL_CMD
-# entries need to be associated with something that goes into /system.
-# ld.config.txt qualifies but it could be anything else in /system until soong
-# supports creation of symlinks. http://b/123333111
-#
-# Keeping the appearance of files/dirs having old locations for apps that have
-# come to rely on them.
-
-# http://b/121248172 - create a link from /system/usr/icu to
-# /apex/com.android.runtime/etc/icu so that apps can find the ICU .dat file.
-# A symlink can't overwrite a directory and the /system/usr/icu directory once
-# existed so the required structure must be created whatever we find.
-LOCAL_POST_INSTALL_CMD = mkdir -p $(TARGET_OUT)/usr && rm -rf $(TARGET_OUT)/usr/icu
-LOCAL_POST_INSTALL_CMD += && ln -sf /apex/com.android.runtime/etc/icu $(TARGET_OUT)/usr/icu
-
-# TODO(b/124106384): Clean up compat symlinks for ART binaries.
-ART_BINARIES := \
-  dalvikvm \
-  dalvikvm32 \
-  dalvikvm64 \
-  dex2oat \
-  dexdiag \
-  dexdump \
-  dexlist \
-  dexoptanalyzer \
-  oatdump \
-  profman \
-
-LOCAL_POST_INSTALL_CMD += && mkdir -p $(TARGET_OUT)/bin
-$(foreach b,$(ART_BINARIES), \
-  $(eval LOCAL_POST_INSTALL_CMD += \
-    && ln -sf /apex/com.android.runtime/bin/$(b) $(TARGET_OUT)/bin/$(b)) \
-)
-
-# End of runtime APEX compatibilty.
-
-ifeq ($(_enforce_vndk_at_runtime),true)
-
-# for VNDK enforced devices
-LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
-include $(BUILD_SYSTEM)/base_rules.mk
-ld_config_template := $(LOCAL_PATH)/etc/ld.config.txt
-check_backward_compatibility := true
-vndk_version := $(PLATFORM_VNDK_VERSION)
-include $(LOCAL_PATH)/update_and_install_ld_config.mk
-
-else ifeq ($(_enforce_vndk_lite_at_runtime),true)
-
-# for treblized but VNDK lightly enforced devices
-LOCAL_MODULE_STEM := ld.config.vndk_lite.txt
-include $(BUILD_SYSTEM)/base_rules.mk
-ld_config_template := $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt
-vndk_version := $(PLATFORM_VNDK_VERSION)
-libz_is_llndk := true
-include $(LOCAL_PATH)/update_and_install_ld_config.mk
-
-else
-
-# for legacy non-treblized devices
-LOCAL_MODULE_STEM := $(LOCAL_MODULE)
-LOCAL_SRC_FILES := etc/ld.config.legacy.txt
-include $(BUILD_PREBUILT)
-
-endif  # ifeq ($(_enforce_vndk_at_runtime),true)
-
-# ld.config.txt for VNDK versions older than PLATFORM_VNDK_VERSION
-# are built with the VNDK libraries lists under /prebuilts/vndk.
-#
-# ld.config.$(VER).txt is built and installed for all VNDK versions
-# listed in PRODUCT_EXTRA_VNDK_VERSIONS.
-#
-# $(1): VNDK version
-define build_versioned_ld_config
-include $(CLEAR_VARS)
-LOCAL_MODULE := ld.config.$(1).txt
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-LOCAL_MODULE_STEM := $$(LOCAL_MODULE)
-include $(BUILD_SYSTEM)/base_rules.mk
-ld_config_template := $(LOCAL_PATH)/etc/ld.config.txt
-check_backward_compatibility := true
-vndk_version := $(1)
-lib_list_from_prebuilts := true
-include $(LOCAL_PATH)/update_and_install_ld_config.mk
-endef
-
-vndk_snapshots := $(wildcard prebuilts/vndk/*)
-supported_vndk_snapshot_versions := \
-  $(strip $(patsubst prebuilts/vndk/v%,%,$(vndk_snapshots)))
-$(foreach ver,$(supported_vndk_snapshot_versions),\
-  $(eval $(call build_versioned_ld_config,$(ver))))
-
-vndk_snapshots :=
-supported_vndk_snapshot_versions :=
-
-#######################################
-# ld.config.vndk_lite.txt
-#
-# This module is only for GSI.
-#
-ifeq ($(_enforce_vndk_lite_at_runtime),false)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := ld.config.vndk_lite.txt
+LOCAL_MODULE := sanitizer.libraries.txt
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
 LOCAL_MODULE_STEM := $(LOCAL_MODULE)
 include $(BUILD_SYSTEM)/base_rules.mk
-ld_config_template := $(LOCAL_PATH)/etc/ld.config.vndk_lite.txt
-vndk_version := $(PLATFORM_VNDK_VERSION)
-libz_is_llndk := true
-include $(LOCAL_PATH)/update_and_install_ld_config.mk
-
-endif  # ifeq ($(_enforce_vndk_lite_at_runtime),false)
-
-_enforce_vndk_at_runtime :=
-_enforce_vndk_lite_at_runtime :=
-
-#######################################
-# ld.config.txt for recovery
-include $(CLEAR_VARS)
-LOCAL_MODULE := ld.config.recovery.txt
-LOCAL_MODULE_CLASS := ETC
-LOCAL_SRC_FILES := etc/ld.config.recovery.txt
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/etc
-LOCAL_MODULE_STEM := ld.config.txt
-include $(BUILD_PREBUILT)
-
-#######################################
-# llndk.libraries.txt
-include $(CLEAR_VARS)
-LOCAL_MODULE := llndk.libraries.txt
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES := $(LLNDK_LIBRARIES)
+$(LOCAL_BUILT_MODULE): PRIVATE_SANITIZER_RUNTIME_LIBRARIES := $(addsuffix .so,\
+  $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+  $(HWADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+  $(UBSAN_RUNTIME_LIBRARY) \
+  $(TSAN_RUNTIME_LIBRARY) \
+  $(2ND_ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+  $(2ND_HWADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+  $(2ND_UBSAN_RUNTIME_LIBRARY) \
+  $(2ND_TSAN_RUNTIME_LIBRARY))
 $(LOCAL_BUILT_MODULE):
 	@echo "Generate: $@"
 	@mkdir -p $(dir $@)
 	$(hide) echo -n > $@
-	$(hide) $(foreach lib,$(PRIVATE_LLNDK_LIBRARIES), \
-		echo $(lib).so >> $@;)
-
-#######################################
-# vndksp.libraries.txt
-include $(CLEAR_VARS)
-LOCAL_MODULE := vndksp.libraries.txt
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-LOCAL_MODULE_STEM := $(call append_vndk_version,$(LOCAL_MODULE))
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(VNDK_SAMEPROCESS_LIBRARIES)
-$(LOCAL_BUILT_MODULE):
-	@echo "Generate: $@"
-	@mkdir -p $(dir $@)
-	$(hide) echo -n > $@
-	$(hide) $(foreach lib,$(PRIVATE_VNDK_SAMEPROCESS_LIBRARIES), \
-		echo $(lib).so >> $@;)
+	$(hide) $(foreach lib,$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES), \
+		echo $(lib) >> $@;)
 
 #######################################
 # adb_debug.prop in debug ramdisk
diff --git a/rootdir/avb/Android.bp b/rootdir/avb/Android.bp
new file mode 100644
index 0000000..85d2786
--- /dev/null
+++ b/rootdir/avb/Android.bp
@@ -0,0 +1,20 @@
+filegroup {
+    name: "q-gsi_avbpubkey",
+    srcs: [
+        "q-gsi.avbpubkey",
+    ],
+}
+
+filegroup {
+    name: "r-gsi_avbpubkey",
+    srcs: [
+        "r-gsi.avbpubkey",
+    ],
+}
+
+filegroup {
+    name: "s-gsi_avbpubkey",
+    srcs: [
+        "s-gsi.avbpubkey",
+    ],
+}
diff --git a/rootdir/avb/Android.mk b/rootdir/avb/Android.mk
index 5dc019c..80573fb 100644
--- a/rootdir/avb/Android.mk
+++ b/rootdir/avb/Android.mk
@@ -16,6 +16,21 @@
 include $(BUILD_PREBUILT)
 
 #######################################
+# q-developer-gsi.avbpubkey
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := q-developer-gsi.avbpubkey
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
+else
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
+endif
+
+include $(BUILD_PREBUILT)
+
+#######################################
 # r-gsi.avbpubkey
 include $(CLEAR_VARS)
 
diff --git a/rootdir/avb/q-developer-gsi.avbpubkey b/rootdir/avb/q-developer-gsi.avbpubkey
new file mode 100644
index 0000000..0ace69d
--- /dev/null
+++ b/rootdir/avb/q-developer-gsi.avbpubkey
Binary files differ
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 5aac61b..5c87843 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -1,167 +1,3 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Bionic loader config file.
-# This gives the exactly the same namespace setup in pre-O.
-#
-
-# All binaries gets the same configuration 'legacy'
-dir.legacy = /system
-dir.legacy = /product
-dir.legacy = /vendor
-dir.legacy = /odm
-dir.legacy = /sbin
-
-# Except for /postinstall, where only /system and /product are searched
-dir.postinstall = /postinstall
-
-# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
-# This must be last.
-dir.legacy = /data
-
-[legacy]
-namespace.default.isolated = false
-
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /product/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
-namespace.default.search.paths += /odm/${LIB}
-
-namespace.default.asan.search.paths  = /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/product/${LIB}
-namespace.default.asan.search.paths +=           /product/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-
-###############################################################################
-# APEX related namespaces.
-###############################################################################
-
-additional.namespaces = runtime,conscrypt,media,resolv
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-# If a shared library or an executable requests a shared library that
-# cannot be loaded into the default namespace, the dynamic linker tries
-# to load the shared library from the runtime namespace. And then, if the
-# shared library cannot be loaded from the runtime namespace either, the
-# dynamic linker tries to load the shared library from the resolv namespace.
-# Finally, if all attempts fail, the dynamic linker returns an error.
-namespace.default.links = runtime,resolv
-namespace.default.asan.links = runtime,resolv
-# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
-# libart.
-namespace.default.visible = true
-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
-namespace.default.link.runtime.shared_libs += libandroidicu.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.default.link.runtime.shared_libs += libicui18n.so
-namespace.default.link.runtime.shared_libs += libicuuc.so
-
-# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-namespace.default.link.runtime.shared_libs += libpac.so
-
-# When libnetd_resolv.so can't be found in the default namespace, search for it
-# in the resolv namespace. Don't allow any other libraries from the resolv namespace
-# to be loaded in the default namespace.
-namespace.default.link.resolv.shared_libs = libnetd_resolv.so
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# 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}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = default
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# "media" APEX namespace
-#
-# This namespace is for libraries within the media APEX.
-###############################################################################
-namespace.media.isolated = true
-namespace.media.visible = true
-
-namespace.media.search.paths = /apex/com.android.media/${LIB}
-namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
-
-namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
-
-namespace.media.links = default
-namespace.media.link.default.shared_libs  = libbinder_ndk.so
-namespace.media.link.default.shared_libs += libc.so
-namespace.media.link.default.shared_libs += libcgrouprc.so
-namespace.media.link.default.shared_libs += libdl.so
-namespace.media.link.default.shared_libs += liblog.so
-namespace.media.link.default.shared_libs += libmediametrics.so
-namespace.media.link.default.shared_libs += libmediandk.so
-namespace.media.link.default.shared_libs += libm.so
-namespace.media.link.default.shared_libs += libvndksupport.so
-
-namespace.media.link.default.shared_libs += libclang_rt.asan-aarch64-android.so
-namespace.media.link.default.shared_libs += libclang_rt.asan-arm-android.so
-namespace.media.link.default.shared_libs += libclang_rt.asan-i686-android.so
-namespace.media.link.default.shared_libs += libclang_rt.asan-x86_64-android.so
-namespace.media.link.default.shared_libs += libclang_rt.hwasan-aarch64-android.so
-
-###############################################################################
-# "conscrypt" APEX namespace
-#
-# This namespace is for libraries within the conscrypt APEX.
-###############################################################################
-namespace.conscrypt.isolated = true
-namespace.conscrypt.visible = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.links = runtime,default
-namespace.conscrypt.link.runtime.shared_libs  = libandroidio.so
-namespace.conscrypt.link.default.shared_libs  = libc.so
-namespace.conscrypt.link.default.shared_libs += libm.so
-namespace.conscrypt.link.default.shared_libs += libdl.so
-namespace.conscrypt.link.default.shared_libs += liblog.so
-
-###############################################################################
-# "resolv" APEX namespace
-#
-# This namespace is for libraries within the resolv APEX.
-###############################################################################
-namespace.resolv.isolated = true
-namespace.resolv.visible = true
-
-namespace.resolv.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.asan.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.links = default
-namespace.resolv.link.default.shared_libs  = libc.so
-namespace.resolv.link.default.shared_libs += libcgrouprc.so
-namespace.resolv.link.default.shared_libs += libm.so
-namespace.resolv.link.default.shared_libs += libdl.so
-namespace.resolv.link.default.shared_libs += libbinder_ndk.so
-namespace.resolv.link.default.shared_libs += liblog.so
-namespace.resolv.link.default.shared_libs += libvndksupport.so
-
-###############################################################################
-# Namespace config for binaries under /postinstall.
-# Only one default namespace is defined and it has no directories other than
-# /system/lib and /product/lib in the search paths. This is because linker
-# calls realpath on the search paths and this causes selinux denial if the
-# paths (/vendor, /odm) are not allowed to the poinstall binaries.
-# There is no reason to allow the binaries to access the paths.
-###############################################################################
-[postinstall]
-namespace.default.isolated = false
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /product/${LIB}
+# This file is no longer in use.
+# Please update linker configuration generator instead.
+# You can find the code from /system/linkerconfig
\ No newline at end of file
diff --git a/rootdir/etc/ld.config.recovery.txt b/rootdir/etc/ld.config.recovery.txt
index 5d6c01a..5c87843 100644
--- a/rootdir/etc/ld.config.recovery.txt
+++ b/rootdir/etc/ld.config.recovery.txt
@@ -1,9 +1,3 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Bionic loader config file for recovery mode
-#
-
-dir.recovery = /system/bin
-
-[recovery]
-namespace.default.search.paths = /system/${LIB}
+# This file is no longer in use.
+# Please update linker configuration generator instead.
+# You can find the code from /system/linkerconfig
\ No newline at end of file
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index c95f60f..5c87843 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -1,698 +1,3 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Bionic loader config file.
-#
-
-# Don't change the order here. The first pattern that matches with the
-# absolute path of an executable is selected.
-dir.system = /system/bin/
-dir.system = /system/xbin/
-dir.system = /%PRODUCT%/bin/
-
-dir.vendor = /odm/bin/
-dir.vendor = /vendor/bin/
-dir.vendor = /data/nativetest/odm
-dir.vendor = /data/nativetest64/odm
-dir.vendor = /data/benchmarktest/odm
-dir.vendor = /data/benchmarktest64/odm
-dir.vendor = /data/nativetest/vendor
-dir.vendor = /data/nativetest64/vendor
-dir.vendor = /data/benchmarktest/vendor
-dir.vendor = /data/benchmarktest64/vendor
-
-dir.unrestricted = /data/nativetest/unrestricted
-dir.unrestricted = /data/nativetest64/unrestricted
-
-# TODO(b/123864775): Ensure tests are run from /data/nativetest{,64} or (if
-# necessary) the unrestricted subdirs above. Then clean this up.
-dir.unrestricted = /data/local/tmp
-
-dir.postinstall = /postinstall
-
-# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
-# This must be last.
-dir.system = /data
-
-[system]
-additional.namespaces = runtime,conscrypt,media,resolv,sphal,vndk,rs
-
-###############################################################################
-# "default" namespace
-#
-# Framework-side code runs in this namespace. Libs from /vendor partition
-# can't be loaded in this namespace.
-###############################################################################
-namespace.default.isolated = true
-
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /%PRODUCT%/${LIB}
-namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
-
-# We can't have entire /system/${LIB} as permitted paths because doing so
-# makes it possible to load libs in /system/${LIB}/vndk* directories by
-# their absolute paths (e.g. dlopen("/system/lib/vndk/libbase.so");).
-# VNDK libs are built with previous versions of Android and thus must not be
-# loaded into this namespace where libs built with the current version of
-# Android are loaded. Mixing the two types of libs in the same namespace can
-# cause unexpected problem.
-namespace.default.permitted.paths  = /system/${LIB}/drm
-namespace.default.permitted.paths += /system/${LIB}/extractors
-namespace.default.permitted.paths += /system/${LIB}/hw
-namespace.default.permitted.paths += /%PRODUCT%/${LIB}
-namespace.default.permitted.paths += /%PRODUCT_SERVICES%/${LIB}
-# These are where odex files are located. libart has to be able to dlopen the files
-namespace.default.permitted.paths += /system/framework
-namespace.default.permitted.paths += /system/app
-namespace.default.permitted.paths += /system/priv-app
-namespace.default.permitted.paths += /vendor/framework
-namespace.default.permitted.paths += /vendor/app
-namespace.default.permitted.paths += /vendor/priv-app
-namespace.default.permitted.paths += /system/vendor/framework
-namespace.default.permitted.paths += /system/vendor/app
-namespace.default.permitted.paths += /system/vendor/priv-app
-namespace.default.permitted.paths += /odm/framework
-namespace.default.permitted.paths += /odm/app
-namespace.default.permitted.paths += /odm/priv-app
-namespace.default.permitted.paths += /oem/app
-namespace.default.permitted.paths += /%PRODUCT%/framework
-namespace.default.permitted.paths += /%PRODUCT%/app
-namespace.default.permitted.paths += /%PRODUCT%/priv-app
-namespace.default.permitted.paths += /%PRODUCT_SERVICES%/framework
-namespace.default.permitted.paths += /%PRODUCT_SERVICES%/app
-namespace.default.permitted.paths += /%PRODUCT_SERVICES%/priv-app
-namespace.default.permitted.paths += /data
-namespace.default.permitted.paths += /mnt/expand
-namespace.default.permitted.paths += /apex/com.android.runtime/${LIB}/bionic
-namespace.default.permitted.paths += /system/${LIB}/bootstrap
-
-namespace.default.asan.search.paths  = /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/%PRODUCT%/${LIB}
-namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/%PRODUCT_SERVICES%/${LIB}
-namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
-
-namespace.default.asan.permitted.paths  = /data
-namespace.default.asan.permitted.paths += /system/${LIB}/drm
-namespace.default.asan.permitted.paths += /system/${LIB}/extractors
-namespace.default.asan.permitted.paths += /system/${LIB}/hw
-namespace.default.asan.permitted.paths += /system/framework
-namespace.default.asan.permitted.paths += /system/app
-namespace.default.asan.permitted.paths += /system/priv-app
-namespace.default.asan.permitted.paths += /vendor/framework
-namespace.default.asan.permitted.paths += /vendor/app
-namespace.default.asan.permitted.paths += /vendor/priv-app
-namespace.default.asan.permitted.paths += /system/vendor/framework
-namespace.default.asan.permitted.paths += /system/vendor/app
-namespace.default.asan.permitted.paths += /system/vendor/priv-app
-namespace.default.asan.permitted.paths += /odm/framework
-namespace.default.asan.permitted.paths += /odm/app
-namespace.default.asan.permitted.paths += /odm/priv-app
-namespace.default.asan.permitted.paths += /oem/app
-namespace.default.asan.permitted.paths += /%PRODUCT%/${LIB}
-namespace.default.asan.permitted.paths += /%PRODUCT%/framework
-namespace.default.asan.permitted.paths += /%PRODUCT%/app
-namespace.default.asan.permitted.paths += /%PRODUCT%/priv-app
-namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/${LIB}
-namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/framework
-namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/app
-namespace.default.asan.permitted.paths += /%PRODUCT_SERVICES%/priv-app
-namespace.default.asan.permitted.paths += /mnt/expand
-namespace.default.asan.permitted.paths += /apex/com.android.runtime/${LIB}/bionic
-namespace.default.asan.permitted.paths += /system/${LIB}/bootstrap
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-# If a shared library or an executable requests a shared library that
-# cannot be loaded into the default namespace, the dynamic linker tries
-# to load the shared library from the runtime namespace. And then, if the
-# shared library cannot be loaded from the runtime namespace either, the
-# dynamic linker tries to load the shared library from the resolv namespace.
-# Finally, if all attempts fail, the dynamic linker returns an error.
-namespace.default.links = runtime,resolv
-# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
-# libart.
-namespace.default.visible = true
-namespace.default.link.runtime.shared_libs  = libdexfile_external.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.default.link.runtime.shared_libs += libicui18n.so
-namespace.default.link.runtime.shared_libs += libicuuc.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
-namespace.default.link.runtime.shared_libs += libandroidicu.so
-
-# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-namespace.default.link.runtime.shared_libs += libpac.so
-namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-# When libnetd_resolv.so can't be found in the default namespace, search for it
-# in the resolv namespace. Don't allow any other libraries from the resolv namespace
-# to be loaded in the default namespace.
-namespace.default.link.resolv.shared_libs = libnetd_resolv.so
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# 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}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = default
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# "media" APEX namespace
-#
-# This namespace is for libraries within the media APEX.
-###############################################################################
-namespace.media.isolated = true
-namespace.media.visible = true
-
-namespace.media.search.paths = /apex/com.android.media/${LIB}
-namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
-
-namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
-namespace.media.asan.permitted.paths = /apex/com.android.media/${LIB}/extractors
-
-namespace.media.links = default
-namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.media.link.default.shared_libs += libbinder_ndk.so
-namespace.media.link.default.shared_libs += libcgrouprc.so
-namespace.media.link.default.shared_libs += libmediametrics.so
-namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-###############################################################################
-# "conscrypt" APEX namespace
-#
-# This namespace is for libraries within the conscrypt APEX.
-###############################################################################
-namespace.conscrypt.isolated = true
-namespace.conscrypt.visible = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.links = runtime,default
-namespace.conscrypt.link.runtime.shared_libs  = libandroidio.so
-namespace.conscrypt.link.default.shared_libs  = libc.so
-namespace.conscrypt.link.default.shared_libs += libm.so
-namespace.conscrypt.link.default.shared_libs += libdl.so
-namespace.conscrypt.link.default.shared_libs += liblog.so
-
-###############################################################################
-# "resolv" APEX namespace
-#
-# This namespace is for libraries within the resolv APEX.
-###############################################################################
-namespace.resolv.isolated = true
-namespace.resolv.visible = true
-
-namespace.resolv.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.asan.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.links = default
-namespace.resolv.link.default.shared_libs  = libc.so
-namespace.resolv.link.default.shared_libs += libcgrouprc.so
-namespace.resolv.link.default.shared_libs += libm.so
-namespace.resolv.link.default.shared_libs += libdl.so
-namespace.resolv.link.default.shared_libs += libbinder_ndk.so
-namespace.resolv.link.default.shared_libs += liblog.so
-namespace.resolv.link.default.shared_libs += libvndksupport.so
-
-###############################################################################
-# "sphal" namespace
-#
-# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
-# loaded inside system processes. libEGL_<chipset>.so, libGLESv2_<chipset>.so,
-# android.hardware.graphics.mapper@2.0-impl.so, etc are SP-HALs.
-#
-# This namespace is exclusivly for SP-HALs. When the framework tries to dynami-
-# cally load SP-HALs, android_dlopen_ext() is used to explicitly specifying
-# that they should be searched and loaded from this namespace.
-#
-# Note that there is no link from the default namespace to this namespace.
-###############################################################################
-namespace.sphal.isolated = true
-namespace.sphal.visible = true
-
-namespace.sphal.search.paths  = /odm/${LIB}
-namespace.sphal.search.paths += /vendor/${LIB}
-namespace.sphal.search.paths += /vendor/${LIB}/hw
-
-namespace.sphal.permitted.paths  = /odm/${LIB}
-namespace.sphal.permitted.paths += /vendor/${LIB}
-namespace.sphal.permitted.paths += /system/vendor/${LIB}
-
-namespace.sphal.asan.search.paths  = /data/asan/odm/${LIB}
-namespace.sphal.asan.search.paths +=           /odm/${LIB}
-namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.sphal.asan.search.paths +=           /vendor/${LIB}
-
-namespace.sphal.asan.permitted.paths  = /data/asan/odm/${LIB}
-namespace.sphal.asan.permitted.paths +=           /odm/${LIB}
-namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}
-namespace.sphal.asan.permitted.paths +=           /vendor/${LIB}
-
-# Once in this namespace, access to libraries in /system/lib is restricted. Only
-# libs listed here can be used. Order is important here as the namespaces are
-# tried in this order. rs should be before vndk because both are capable
-# of loading libRS_internal.so
-namespace.sphal.links = rs,default,vndk
-
-# Renderscript gets separate namespace
-namespace.sphal.link.rs.shared_libs = libRS_internal.so
-
-namespace.sphal.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.sphal.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
-
-###############################################################################
-# "rs" namespace
-#
-# This namespace is exclusively for Renderscript internal libraries.
-# This namespace has slightly looser restriction than the vndk namespace because
-# of the genuine characteristics of Renderscript; /data is in the permitted path
-# to load the compiled *.so file and libmediandk.so can be used here.
-###############################################################################
-namespace.rs.isolated = true
-namespace.rs.visible = true
-
-namespace.rs.search.paths  = /odm/${LIB}/vndk-sp
-namespace.rs.search.paths += /vendor/${LIB}/vndk-sp
-namespace.rs.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.search.paths += /odm/${LIB}
-namespace.rs.search.paths += /vendor/${LIB}
-
-namespace.rs.permitted.paths  = /odm/${LIB}
-namespace.rs.permitted.paths += /vendor/${LIB}
-namespace.rs.permitted.paths += /system/vendor/${LIB}
-namespace.rs.permitted.paths += /data
-
-namespace.rs.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
-namespace.rs.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.rs.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.rs.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.asan.search.paths += /data/asan/odm/${LIB}
-namespace.rs.asan.search.paths +=           /odm/${LIB}
-namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.rs.asan.search.paths +=           /vendor/${LIB}
-
-namespace.rs.asan.permitted.paths  = /data/asan/odm/${LIB}
-namespace.rs.asan.permitted.paths +=           /odm/${LIB}
-namespace.rs.asan.permitted.paths += /data/asan/vendor/${LIB}
-namespace.rs.asan.permitted.paths +=           /vendor/${LIB}
-namespace.rs.asan.permitted.paths += /data
-
-namespace.rs.links = default,vndk
-
-namespace.rs.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
-# namespace because RS framework libs are using them.
-namespace.rs.link.default.shared_libs += %PRIVATE_LLNDK_LIBRARIES%
-
-namespace.rs.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
-
-###############################################################################
-# "vndk" namespace
-#
-# This namespace is exclusively for vndk-sp libs.
-###############################################################################
-namespace.vndk.isolated = true
-namespace.vndk.visible = true
-
-namespace.vndk.search.paths  = /odm/${LIB}/vndk-sp
-namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
-namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-
-namespace.vndk.permitted.paths  = /odm/${LIB}/hw
-namespace.vndk.permitted.paths += /odm/${LIB}/egl
-namespace.vndk.permitted.paths += /vendor/${LIB}/hw
-namespace.vndk.permitted.paths += /vendor/${LIB}/egl
-namespace.vndk.permitted.paths += /system/vendor/${LIB}/hw
-namespace.vndk.permitted.paths += /system/vendor/${LIB}/egl
-# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
-namespace.vndk.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
-
-namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-
-namespace.vndk.asan.permitted.paths  = /data/asan/odm/${LIB}/hw
-namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/hw
-namespace.vndk.asan.permitted.paths += /data/asan/odm/${LIB}/egl
-namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/egl
-namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/hw
-namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/hw
-namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/egl
-namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/egl
-
-namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
-namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%/hw
-
-# The "vndk" namespace links to "default" namespace for LLNDK libs and links to
-# "sphal" namespace for vendor libs.  The ordering matters.  The "default"
-# namespace has higher priority than the "sphal" namespace.
-namespace.vndk.links = default,sphal,runtime
-
-# When these NDK libs are required inside this namespace, then it is redirected
-# to the default namespace. This is possible since their ABI is stable across
-# Android releases.
-namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
-
-# Allow VNDK-SP extensions to use vendor libraries
-namespace.vndk.link.sphal.allow_all_shared_libs = true
-
-
-###############################################################################
-# Namespace config for vendor processes. In O, no restriction is enforced for
-# them. However, in O-MR1, access to /system/${LIB} will not be allowed to
-# the default namespace. 'system' namespace will be added to give limited
-# (LL-NDK only) access.
-###############################################################################
-[vendor]
-additional.namespaces = runtime,system,vndk%VNDK_IN_SYSTEM_NS%
-
-###############################################################################
-# "default" namespace
-#
-# This is the default linker namespace for a vendor process (a process started
-# from /vendor/bin/*). The main executable and the libs under /vendor/lib[64]
-# are loaded directly into this namespace. However, other libs under the system
-# partition (VNDK and LLNDK libraries) are not loaded here but from the
-# separate namespace 'system'. The delegation to the system namespace is done
-# via the 'namespace.default.link.system.shared_libs' property below.
-#
-# '#VNDK27#' TAG is only for building ld.config.27.txt for backward
-# compatibility. (TODO:b/123390078) Move them to a separate file.
-###############################################################################
-namespace.default.isolated = true
-namespace.default.visible = true
-
-namespace.default.search.paths  = /odm/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
-
-namespace.default.permitted.paths  = /odm
-namespace.default.permitted.paths += /vendor
-namespace.default.permitted.paths += /system/vendor
-#VNDK27#namespace.default.search.paths += /vendor/${LIB}/hw
-#VNDK27#namespace.default.search.paths += /vendor/${LIB}/egl
-
-namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-#VNDK27#namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/hw
-#VNDK27#namespace.default.asan.search.paths +=           /vendor/${LIB}/hw
-#VNDK27#namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/egl
-#VNDK27#namespace.default.asan.search.paths +=           /vendor/${LIB}/egl
-
-namespace.default.asan.permitted.paths  = /data/asan/odm
-namespace.default.asan.permitted.paths +=           /odm
-namespace.default.asan.permitted.paths += /data/asan/vendor
-namespace.default.asan.permitted.paths +=           /vendor
-
-namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS%,runtime
-namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.system.shared_libs  = %LLNDK_LIBRARIES%
-namespace.default.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES%
-namespace.default.link.vndk.shared_libs  = %VNDK_SAMEPROCESS_LIBRARIES%
-namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES%
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# This namespace exposes externally accessible libraries from the Runtime APEX.
-###############################################################################
-namespace.runtime.isolated = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = system
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.system.allow_all_shared_libs = true
-
-###############################################################################
-# "vndk" namespace
-#
-# This namespace is where VNDK and VNDK-SP libraries are loaded for
-# a vendor process.
-###############################################################################
-namespace.vndk.isolated = false
-
-namespace.vndk.search.paths  = /odm/${LIB}/vndk
-namespace.vndk.search.paths += /odm/${LIB}/vndk-sp
-namespace.vndk.search.paths += /vendor/${LIB}/vndk
-namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
-namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.search.paths += /system/${LIB}/vndk%VNDK_VER%
-
-namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk
-namespace.vndk.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
-
-# When these NDK libs are required inside this namespace, then it is redirected
-# to the system namespace. This is possible since their ABI is stable across
-# Android releases.  The links here should be identical to that of the
-# 'vndk_in_system' namespace, except for the link between 'vndk' and
-# 'vndk_in_system'.
-namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS%,runtime
-
-namespace.vndk.link.system.shared_libs  = %LLNDK_LIBRARIES%
-namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.vndk.link.default.allow_all_shared_libs = true
-
-namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.vndk.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES%
-
-###############################################################################
-# "system" namespace
-#
-# This namespace is where system libs (VNDK and LLNDK libs) are loaded for
-# a vendor process.
-###############################################################################
-namespace.system.isolated = false
-
-namespace.system.search.paths  = /system/${LIB}
-namespace.system.search.paths += /%PRODUCT%/${LIB}
-namespace.system.search.paths += /%PRODUCT_SERVICES%/${LIB}
-
-namespace.system.asan.search.paths  = /data/asan/system/${LIB}
-namespace.system.asan.search.paths +=           /system/${LIB}
-namespace.system.asan.search.paths += /data/asan/product/${LIB}
-namespace.system.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.system.asan.search.paths += /data/asan/product_services/${LIB}
-namespace.system.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
-
-namespace.system.links = runtime
-namespace.system.link.runtime.shared_libs  = libdexfile_external.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.system.link.runtime.shared_libs += libicui18n.so
-namespace.system.link.runtime.shared_libs += libicuuc.so
-namespace.system.link.runtime.shared_libs += libnativebridge.so
-namespace.system.link.runtime.shared_libs += libnativehelper.so
-namespace.system.link.runtime.shared_libs += libnativeloader.so
-# Workaround for b/124772622
-namespace.system.link.runtime.shared_libs += libandroidicu.so
-namespace.system.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-###############################################################################
-# "vndk_in_system" namespace
-#
-# This namespace is where no-vendor-variant VNDK libraries are loaded for a
-# vendor process.  Note that we do not simply export these libraries from
-# "system" namespace, because in some case both the core variant and the
-# vendor variant of a VNDK library may be loaded.  In such case, we do not
-# want to eliminate double-loading because doing so means the global states
-# of the library would be shared.
-#
-# Only the no-vendor-variant VNDK libraries are whitelisted in this namespace.
-# This is to ensure that we do not load libraries needed by no-vendor-variant
-# VNDK libraries into vndk_in_system namespace.
-###############################################################################
-namespace.vndk_in_system.isolated = true
-namespace.vndk_in_system.visible = true
-
-# The search paths here should be kept the same as that of the 'system'
-# namespace.
-namespace.vndk_in_system.search.paths  = /system/${LIB}
-namespace.vndk_in_system.search.paths += /%PRODUCT%/${LIB}
-namespace.vndk_in_system.search.paths += /%PRODUCT_SERVICES%/${LIB}
-
-namespace.vndk_in_system.asan.search.paths  = /data/asan/system/${LIB}
-namespace.vndk_in_system.asan.search.paths +=           /system/${LIB}
-namespace.vndk_in_system.asan.search.paths += /data/asan/product/${LIB}
-namespace.vndk_in_system.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.vndk_in_system.asan.search.paths += /data/asan/product_services/${LIB}
-namespace.vndk_in_system.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
-
-namespace.vndk_in_system.whitelisted = %VNDK_USING_CORE_VARIANT_LIBRARIES%
-
-# The links here should be identical to that of the 'vndk' namespace, with the
-# following exception:
-#   1. 'vndk_in_system' needs to be freely linked back to 'vndk'.
-#   2. 'vndk_in_system' does not need to link to 'default', as any library that
-#      requires anything vendor would not be a vndk_in_system library.
-namespace.vndk_in_system.links = vndk,system,runtime
-namespace.vndk_in_system.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.vndk_in_system.link.system.shared_libs  = %LLNDK_LIBRARIES%
-namespace.vndk_in_system.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.vndk_in_system.link.vndk.allow_all_shared_libs = true
-
-
-###############################################################################
-# Namespace config for native tests that need access to both system and vendor
-# libraries. This replicates the default linker config (done by
-# init_default_namespace_no_config in bionic/linker/linker.cpp), except that it
-# includes the requisite namespace setup for APEXes.
-###############################################################################
-[unrestricted]
-additional.namespaces = runtime,media,conscrypt,resolv
-
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /odm/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
-
-namespace.default.asan.search.paths  = /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.default.links = runtime,resolv
-namespace.default.visible = true
-
-namespace.default.link.runtime.shared_libs  = libdexfile_external.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.default.link.runtime.shared_libs += libicui18n.so
-namespace.default.link.runtime.shared_libs += libicuuc.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
-namespace.default.link.runtime.shared_libs += libandroidicu.so
-
-# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-namespace.default.link.runtime.shared_libs += libpac.so
-namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.default.link.resolv.shared_libs = libnetd_resolv.so
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# 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}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = default
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# "media" APEX namespace
-#
-# This namespace is for libraries within the media APEX.
-###############################################################################
-namespace.media.isolated = true
-namespace.media.visible = true
-
-namespace.media.search.paths = /apex/com.android.media/${LIB}
-namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
-
-namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
-namespace.media.asan.permitted.paths = /apex/com.android.media/${LIB}/extractors
-
-namespace.media.links = default
-namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.media.link.default.shared_libs += libbinder_ndk.so
-namespace.media.link.default.shared_libs += libmediametrics.so
-namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-###############################################################################
-# "conscrypt" APEX namespace
-#
-# This namespace is for libraries within the conscrypt APEX.
-###############################################################################
-namespace.conscrypt.isolated = true
-namespace.conscrypt.visible = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.links = runtime,default
-namespace.conscrypt.link.runtime.shared_libs  = libandroidio.so
-namespace.conscrypt.link.default.shared_libs  = libc.so
-namespace.conscrypt.link.default.shared_libs += libm.so
-namespace.conscrypt.link.default.shared_libs += libdl.so
-namespace.conscrypt.link.default.shared_libs += liblog.so
-
-###############################################################################
-# "resolv" APEX namespace
-#
-# This namespace is for libraries within the resolv APEX.
-###############################################################################
-namespace.resolv.isolated = true
-namespace.resolv.visible = true
-
-namespace.resolv.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.asan.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.links = default
-namespace.resolv.link.default.shared_libs  = libc.so
-namespace.resolv.link.default.shared_libs += libm.so
-namespace.resolv.link.default.shared_libs += libdl.so
-namespace.resolv.link.default.shared_libs += libbinder_ndk.so
-namespace.resolv.link.default.shared_libs += liblog.so
-
-
-###############################################################################
-# Namespace config for binaries under /postinstall.
-# Only default namespace is defined and default has no directories
-# other than /system/lib in the search paths. This is because linker calls
-# realpath on the search paths and this causes selinux denial if the paths
-# (/vendor, /odm) are not allowed to the postinstall binaries. There is no
-# reason to allow the binaries to access the paths.
-###############################################################################
-[postinstall]
-namespace.default.isolated = false
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /%PRODUCT%/${LIB}
-namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
-
-namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES%
+# This file is no longer in use.
+# Please update linker configuration generator instead.
+# You can find the code from /system/linkerconfig
\ No newline at end of file
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 5642559..5c87843 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -1,505 +1,3 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Bionic loader config file.
-#
-
-# Don't change the order here. The first pattern that matches with the
-# absolute path of an executable is selected.
-dir.system = /system/bin/
-dir.system = /system/xbin/
-dir.system = /%PRODUCT%/bin/
-
-dir.vendor = /odm/bin/
-dir.vendor = /vendor/bin/
-dir.vendor = /data/nativetest/odm
-dir.vendor = /data/nativetest64/odm
-dir.vendor = /data/benchmarktest/odm
-dir.vendor = /data/benchmarktest64/odm
-dir.vendor = /data/nativetest/vendor
-dir.vendor = /data/nativetest64/vendor
-dir.vendor = /data/benchmarktest/vendor
-dir.vendor = /data/benchmarktest64/vendor
-
-dir.unrestricted = /data/nativetest/unrestricted
-dir.unrestricted = /data/nativetest64/unrestricted
-
-# TODO(b/123864775): Ensure tests are run from /data/nativetest{,64} or (if
-# necessary) the unrestricted subdirs above. Then clean this up.
-dir.unrestricted = /data/local/tmp
-
-dir.postinstall = /postinstall
-
-# Fallback entry to provide APEX namespace lookups for binaries anywhere else.
-# This must be last.
-dir.system = /data
-
-[system]
-additional.namespaces = runtime,conscrypt,media,resolv,sphal,vndk,rs
-
-###############################################################################
-# "default" namespace
-#
-# Framework-side code runs in this namespace. However, libs from other
-# partitions are also allowed temporarily.
-###############################################################################
-namespace.default.isolated = false
-
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /odm/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
-namespace.default.search.paths += /%PRODUCT%/${LIB}
-namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
-
-namespace.default.asan.search.paths  = /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-namespace.default.asan.search.paths += /data/asan/%PRODUCT%/${LIB}
-namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/%PRODUCT_SERVICES%/${LIB}
-namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
-
-# Keep in sync with the platform namespace in the com.android.runtime APEX
-# ld.config.txt.
-# If a shared library or an executable requests a shared library that
-# cannot be loaded into the default namespace, the dynamic linker tries
-# to load the shared library from the runtime namespace. And then, if the
-# shared library cannot be loaded from the runtime namespace either, the
-# dynamic linker tries to load the shared library from the resolv namespace.
-# Finally, if all attempts fail, the dynamic linker returns an error.
-namespace.default.links = runtime,resolv
-# Visible because some libraries are dlopen'ed, e.g. libopenjdk is dlopen'ed by
-# libart.
-namespace.default.visible = true
-namespace.default.link.runtime.shared_libs  = libdexfile_external.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.default.link.runtime.shared_libs += libicui18n.so
-namespace.default.link.runtime.shared_libs += libicuuc.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
-namespace.default.link.runtime.shared_libs += libandroidicu.so
-
-# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-namespace.default.link.runtime.shared_libs += libpac.so
-
-# When libnetd_resolv.so can't be found in the default namespace, search for it
-# in the resolv namespace. Don't allow any other libraries from the resolv namespace
-# to be loaded in the default namespace.
-namespace.default.link.resolv.shared_libs = libnetd_resolv.so
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# 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.
-namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = default
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# "media" APEX namespace
-#
-# This namespace is for libraries within the media APEX.
-###############################################################################
-namespace.media.isolated = true
-namespace.media.visible = true
-
-namespace.media.search.paths = /apex/com.android.media/${LIB}
-namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
-
-namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
-
-namespace.media.links = default
-namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.media.link.default.shared_libs += libbinder_ndk.so
-namespace.media.link.default.shared_libs += libmediametrics.so
-namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-###############################################################################
-# "conscrypt" APEX namespace
-#
-# This namespace is for libraries within the conscrypt APEX.
-###############################################################################
-namespace.conscrypt.isolated = true
-namespace.conscrypt.visible = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.links = runtime,default
-namespace.conscrypt.link.runtime.shared_libs  = libandroidio.so
-namespace.conscrypt.link.default.shared_libs  = libc.so
-namespace.conscrypt.link.default.shared_libs += libm.so
-namespace.conscrypt.link.default.shared_libs += libdl.so
-namespace.conscrypt.link.default.shared_libs += liblog.so
-
-###############################################################################
-# "resolv" APEX namespace
-#
-# This namespace is for libraries within the resolv APEX.
-###############################################################################
-namespace.resolv.isolated = true
-namespace.resolv.visible = true
-
-namespace.resolv.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.asan.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.links = default
-namespace.resolv.link.default.shared_libs  = libc.so
-namespace.resolv.link.default.shared_libs += libcgrouprc.so
-namespace.resolv.link.default.shared_libs += libm.so
-namespace.resolv.link.default.shared_libs += libdl.so
-namespace.resolv.link.default.shared_libs += libbinder_ndk.so
-namespace.resolv.link.default.shared_libs += liblog.so
-namespace.resolv.link.default.shared_libs += libvndksupport.so
-
-###############################################################################
-# "sphal" namespace
-#
-# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
-# loaded inside system processes. libEGL_<chipset>.so, libGLESv2_<chipset>.so,
-# android.hardware.graphics.mapper@2.0-impl.so, etc are SP-HALs.
-#
-# This namespace is exclusivly for SP-HALs. When the framework tries to dynami-
-# cally load SP-HALs, android_dlopen_ext() is used to explicitly specifying
-# that they should be searched and loaded from this namespace.
-#
-# Note that there is no link from the default namespace to this namespace.
-###############################################################################
-namespace.sphal.isolated = true
-namespace.sphal.visible = true
-
-namespace.sphal.search.paths  = /odm/${LIB}
-namespace.sphal.search.paths += /vendor/${LIB}
-namespace.sphal.search.paths += /vendor/${LIB}/hw
-
-namespace.sphal.permitted.paths  = /odm/${LIB}
-namespace.sphal.permitted.paths += /vendor/${LIB}
-namespace.sphal.permitted.paths += /system/vendor/${LIB}
-
-namespace.sphal.asan.search.paths  = /data/asan/odm/${LIB}
-namespace.sphal.asan.search.paths +=           /odm/${LIB}
-namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.sphal.asan.search.paths +=           /vendor/${LIB}
-
-namespace.sphal.asan.permitted.paths  = /data/asan/odm/${LIB}
-namespace.sphal.asan.permitted.paths +=           /odm/${LIB}
-namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}
-namespace.sphal.asan.permitted.paths +=           /vendor/${LIB}
-
-# Once in this namespace, access to libraries in /system/lib is restricted. Only
-# libs listed here can be used. Order is important here as the namespaces are
-# tried in this order. rs should be before vndk because both are capable
-# of loading libRS_internal.so
-namespace.sphal.links = rs,default,vndk
-
-# Renderscript gets separate namespace
-namespace.sphal.link.rs.shared_libs = libRS_internal.so
-
-namespace.sphal.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.sphal.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.sphal.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
-
-###############################################################################
-# "rs" namespace
-#
-# This namespace is exclusively for Renderscript internal libraries.
-# This namespace has slightly looser restriction than the vndk namespace because
-# of the genuine characteristics of Renderscript; /data is in the permitted path
-# to load the compiled *.so file and libmediandk.so can be used here.
-###############################################################################
-namespace.rs.isolated = true
-namespace.rs.visible = true
-
-namespace.rs.search.paths  = /odm/${LIB}/vndk-sp
-namespace.rs.search.paths += /vendor/${LIB}/vndk-sp
-namespace.rs.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.search.paths += /odm/${LIB}
-namespace.rs.search.paths += /vendor/${LIB}
-
-namespace.rs.permitted.paths  = /odm/${LIB}
-namespace.rs.permitted.paths += /vendor/${LIB}
-namespace.rs.permitted.paths += /system/vendor/${LIB}
-namespace.rs.permitted.paths += /data
-
-namespace.rs.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
-namespace.rs.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.rs.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.rs.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.rs.asan.search.paths += /data/asan/odm/${LIB}
-namespace.rs.asan.search.paths +=           /odm/${LIB}
-namespace.rs.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.rs.asan.search.paths +=           /vendor/${LIB}
-
-namespace.rs.asan.permitted.paths  = /data/asan/odm/${LIB}
-namespace.rs.asan.permitted.paths +=           /odm/${LIB}
-namespace.rs.asan.permitted.paths += /data/asan/vendor/${LIB}
-namespace.rs.asan.permitted.paths +=           /vendor/${LIB}
-namespace.rs.asan.permitted.paths += /data
-
-namespace.rs.links = default,vndk
-
-namespace.rs.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.rs.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-# Private LLNDK libs (e.g. libft2.so) are exceptionally allowed to this
-# namespace because RS framework libs are using them.
-namespace.rs.link.default.shared_libs += %PRIVATE_LLNDK_LIBRARIES%
-
-namespace.rs.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES%
-
-###############################################################################
-# "vndk" namespace
-#
-# This namespace is exclusively for vndk-sp libs.
-###############################################################################
-namespace.vndk.isolated = true
-namespace.vndk.visible = true
-
-namespace.vndk.search.paths  = /odm/${LIB}/vndk-sp
-namespace.vndk.search.paths += /vendor/${LIB}/vndk-sp
-namespace.vndk.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-
-namespace.vndk.permitted.paths  = /odm/${LIB}/hw
-namespace.vndk.permitted.paths += /odm/${LIB}/egl
-namespace.vndk.permitted.paths += /vendor/${LIB}/hw
-namespace.vndk.permitted.paths += /vendor/${LIB}/egl
-namespace.vndk.permitted.paths += /system/vendor/${LIB}/egl
-# This is exceptionally required since android.hidl.memory@1.0-impl.so is here
-namespace.vndk.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER%/hw
-
-namespace.vndk.asan.search.paths  = /data/asan/odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.vndk.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.vndk.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-
-namespace.vndk.asan.permitted.paths  = /data/asan/odm/${LIB}/hw
-namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/hw
-namespace.vndk.asan.permitted.paths += /data/asan/odm/${LIB}/egl
-namespace.vndk.asan.permitted.paths +=           /odm/${LIB}/egl
-namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/hw
-namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/hw
-namespace.vndk.asan.permitted.paths += /data/asan/vendor/${LIB}/egl
-namespace.vndk.asan.permitted.paths +=           /vendor/${LIB}/egl
-
-namespace.vndk.asan.permitted.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%/hw
-namespace.vndk.asan.permitted.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%/hw
-
-# When these NDK libs are required inside this namespace, then it is redirected
-# to the default namespace. This is possible since their ABI is stable across
-# Android releases.
-namespace.vndk.links = default
-
-namespace.vndk.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-
-###############################################################################
-# Namespace config for vendor processes. In O, no restriction is enforced for
-# them. However, in O-MR1, access to /system/${LIB} will not be allowed to
-# the default namespace. 'system' namespace will be added to give limited
-# (LL-NDK only) access.
-###############################################################################
-[vendor]
-additional.namespaces = runtime
-
-namespace.default.isolated = false
-
-namespace.default.search.paths  = /odm/${LIB}
-namespace.default.search.paths += /odm/${LIB}/vndk
-namespace.default.search.paths += /odm/${LIB}/vndk-sp
-namespace.default.search.paths += /vendor/${LIB}
-namespace.default.search.paths += /vendor/${LIB}/vndk
-namespace.default.search.paths += /vendor/${LIB}/vndk-sp
-
-# Access to system libraries is allowed
-namespace.default.search.paths += /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.search.paths += /system/${LIB}
-namespace.default.search.paths += /%PRODUCT%/${LIB}
-namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
-namespace.default.search.paths += /system/${LIB}/vndk%VNDK_VER%
-
-namespace.default.asan.search.paths  = /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}/vndk
-namespace.default.asan.search.paths +=           /odm/${LIB}/vndk
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}/vndk-sp
-namespace.default.asan.search.paths +=           /odm/${LIB}/vndk-sp
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk
-namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}/vndk-sp
-namespace.default.asan.search.paths +=           /vendor/${LIB}/vndk-sp
-namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.asan.search.paths +=           /system/${LIB}/vndk-sp%VNDK_VER%
-namespace.default.asan.search.paths += /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/product/${LIB}
-namespace.default.asan.search.paths +=           /%PRODUCT%/${LIB}
-namespace.default.asan.search.paths += /data/asan/product_services/${LIB}
-namespace.default.asan.search.paths +=           /%PRODUCT_SERVICES%/${LIB}
-namespace.default.asan.search.paths += /data/asan/system/${LIB}/vndk%VNDK_VER%
-namespace.default.asan.search.paths +=           /system/${LIB}/vndk%VNDK_VER%
-
-namespace.default.links = runtime
-namespace.default.link.runtime.shared_libs  = libdexfile_external.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.default.link.runtime.shared_libs += libicui18n.so
-namespace.default.link.runtime.shared_libs += libicuuc.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
-# Workaround for b/124772622
-namespace.default.link.runtime.shared_libs += libandroidicu.so
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# This namespace exposes externally accessible libraries from the Runtime APEX.
-###############################################################################
-namespace.runtime.isolated = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.runtime.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = default
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# Namespace config for native tests that need access to both system and vendor
-# libraries. This replicates the default linker config (done by
-# init_default_namespace_no_config in bionic/linker/linker.cpp), except that it
-# includes the requisite namespace setup for APEXes.
-###############################################################################
-[unrestricted]
-additional.namespaces = runtime,media,conscrypt,resolv
-
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /odm/${LIB}
-namespace.default.search.paths += /vendor/${LIB}
-
-namespace.default.asan.search.paths  = /data/asan/system/${LIB}
-namespace.default.asan.search.paths +=           /system/${LIB}
-namespace.default.asan.search.paths += /data/asan/odm/${LIB}
-namespace.default.asan.search.paths +=           /odm/${LIB}
-namespace.default.asan.search.paths += /data/asan/vendor/${LIB}
-namespace.default.asan.search.paths +=           /vendor/${LIB}
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.default.links = runtime,resolv
-namespace.default.visible = true
-
-namespace.default.link.runtime.shared_libs  = libdexfile_external.so
-# libicuuc.so and libicui18n.so are kept for app compat reason. http://b/130788466
-namespace.default.link.runtime.shared_libs += libicui18n.so
-namespace.default.link.runtime.shared_libs += libicuuc.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
-namespace.default.link.runtime.shared_libs += libandroidicu.so
-
-# TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-namespace.default.link.runtime.shared_libs += libpac.so
-namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-namespace.default.link.resolv.shared_libs = libnetd_resolv.so
-
-###############################################################################
-# "runtime" APEX namespace
-#
-# 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}
-namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB}
-namespace.runtime.links = default
-# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
-# when it exists.
-namespace.runtime.link.default.allow_all_shared_libs = true
-
-###############################################################################
-# "media" APEX namespace
-#
-# This namespace is for libraries within the media APEX.
-###############################################################################
-namespace.media.isolated = true
-namespace.media.visible = true
-
-namespace.media.search.paths = /apex/com.android.media/${LIB}
-namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
-
-namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
-
-namespace.media.links = default
-namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
-namespace.media.link.default.shared_libs += libbinder_ndk.so
-namespace.media.link.default.shared_libs += libmediametrics.so
-namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-
-###############################################################################
-# "conscrypt" APEX namespace
-#
-# This namespace is for libraries within the conscrypt APEX.
-###############################################################################
-namespace.conscrypt.isolated = true
-namespace.conscrypt.visible = true
-
-# Keep in sync with ld.config.txt in the com.android.runtime APEX.
-namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.asan.search.paths = /apex/com.android.conscrypt/${LIB}
-namespace.conscrypt.links = runtime,default
-namespace.conscrypt.link.runtime.shared_libs  = libandroidio.so
-namespace.conscrypt.link.default.shared_libs  = libc.so
-namespace.conscrypt.link.default.shared_libs += libm.so
-namespace.conscrypt.link.default.shared_libs += libdl.so
-
-###############################################################################
-# "resolv" APEX namespace
-#
-# This namespace is for libraries within the resolv APEX.
-###############################################################################
-namespace.resolv.isolated = true
-namespace.resolv.visible = true
-
-namespace.resolv.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.asan.search.paths = /apex/com.android.resolv/${LIB}
-namespace.resolv.links = default
-namespace.resolv.link.default.shared_libs  = libc.so
-namespace.resolv.link.default.shared_libs += libcgrouprc.so
-namespace.resolv.link.default.shared_libs += libm.so
-namespace.resolv.link.default.shared_libs += libdl.so
-namespace.resolv.link.default.shared_libs += libbinder_ndk.so
-
-###############################################################################
-# Namespace config for binaries under /postinstall.
-# Only default namespace is defined and default has no directories
-# other than /system/lib in the search paths. This is because linker calls
-# realpath on the search paths and this causes selinux denial if the paths
-# (/vendor, /odm) are not allowed to the postinstall binaries. There is no
-# reason to allow the binaries to access the paths.
-###############################################################################
-[postinstall]
-namespace.default.isolated = false
-namespace.default.search.paths  = /system/${LIB}
-namespace.default.search.paths += /%PRODUCT%/${LIB}
-namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB}
+# This file is no longer in use.
+# Please update linker configuration generator instead.
+# You can find the code from /system/linkerconfig
\ No newline at end of file
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index 27e855f..405f5a9 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -17,7 +17,7 @@
 libmediandk.so
 libm.so
 libnativewindow.so
-libneuralnetworks.so
+libneuralnetworks.so nopreload
 libOpenMAXAL.so
 libOpenSLES.so
 libRS.so
diff --git a/rootdir/fsverity_init.sh b/rootdir/fsverity_init.sh
deleted file mode 100644
index 29e4519..0000000
--- a/rootdir/fsverity_init.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/system/bin/sh
-#
-# 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.
-#
-
-# Enforce fsverity signature checking
-echo 1 > /proc/sys/fs/verity/require_signatures
-
-# Load all keys
-for cert in /product/etc/security/fsverity/*.der; do
-  /system/bin/mini-keyctl padd asymmetric fsv_product .fs-verity < "$cert" ||
-    log -p e -t fsverity_init "Failed to load $cert"
-done
-
-# Prevent future key links to .fs-verity keyring
-/system/bin/mini-keyctl restrict_keyring .fs-verity ||
-  log -p e -t fsverity_init "Failed to restrict .fs-verity keyring"
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 455c9a8..50005d9 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -5,7 +5,8 @@
     export ANDROID_ASSETS /system/app
     export ANDROID_DATA /data
     export ANDROID_STORAGE /storage
-    export ANDROID_RUNTIME_ROOT /apex/com.android.runtime
+    export ANDROID_ART_ROOT /apex/com.android.art
+    export ANDROID_I18N_ROOT /apex/com.android.i18n
     export ANDROID_TZDATA_ROOT /apex/com.android.tzdata
     export EXTERNAL_STORAGE /sdcard
     export ASEC_MOUNTPOINT /mnt/asec
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0fa9feb..7a3339d 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -5,11 +5,11 @@
 #
 
 import /init.environ.rc
-import /init.usb.rc
+import /system/etc/init/hw/init.usb.rc
 import /init.${ro.hardware}.rc
 import /vendor/etc/init/hw/init.${ro.hardware}.rc
-import /init.usb.configfs.rc
-import /init.${ro.zygote}.rc
+import /system/etc/init/hw/init.usb.configfs.rc
+import /system/etc/init/hw/init.${ro.zygote}.rc
 
 # Cgroups are mounted right before early-init using list from /etc/cgroups.json
 on early-init
@@ -32,6 +32,25 @@
     # cgroup for system_server and surfaceflinger
     mkdir /dev/memcg/system 0550 system system
 
+    # set RLIMIT_NICE to allow priorities from 19 to -20
+    setrlimit nice 40 40
+
+    # Allow up to 32K FDs per process
+    setrlimit nofile 32768 32768
+
+    # Set up linker config subdirectories based on mount namespaces
+    mkdir /linkerconfig/bootstrap 0755
+    mkdir /linkerconfig/default 0755
+
+    # Generate ld.config.txt for early executed processes
+    exec -- /system/bin/linkerconfig --target /linkerconfig/bootstrap
+    chmod 644 /linkerconfig/bootstrap/ld.config.txt
+    copy /linkerconfig/bootstrap/ld.config.txt /linkerconfig/default/ld.config.txt
+    chmod 644 /linkerconfig/default/ld.config.txt
+
+    # Mount bootstrap linker configuration as current
+    mount none /linkerconfig/bootstrap /linkerconfig bind rec
+
     start ueventd
 
     # Run apexd-bootstrap so that APEXes that provide critical libraries
@@ -39,6 +58,43 @@
     # the libraries are available to the processes started after this statement.
     exec_start apexd-bootstrap
 
+    # Generate linker config based on apex mounted in bootstrap namespace
+    update_linker_config
+
+    # These must already exist by the time boringssl_self_test32 / boringssl_self_test64 run.
+    mkdir /dev/boringssl 0755 root root
+    mkdir /dev/boringssl/selftest 0755 root root
+
+# Run boringssl self test for each ABI so that later processes can skip it. http://b/139348610
+on early-init && property:ro.product.cpu.abilist32=*
+    exec_start boringssl_self_test32
+on early-init && property:ro.product.cpu.abilist64=*
+    exec_start boringssl_self_test64
+on property:apexd.status=ready && property:ro.product.cpu.abilist32=*
+    exec_start boringssl_self_test_apex32
+on property:apexd.status=ready && property:ro.product.cpu.abilist64=*
+    exec_start boringssl_self_test_apex64
+
+service boringssl_self_test32 /system/bin/boringssl_self_test32
+    setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
+    reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
+
+service boringssl_self_test64 /system/bin/boringssl_self_test64
+    setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
+    reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
+
+service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
+    setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
+    reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
+
+service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
+    setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
+    reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
+
 on init
     sysclktz 0
 
@@ -108,6 +164,17 @@
     mkdir /mnt/media_rw 0750 root media_rw
     mkdir /mnt/user 0755 root root
     mkdir /mnt/user/0 0755 root root
+    mkdir /mnt/user/0/self 0755 root root
+    mkdir /mnt/user/0/emulated 0755 root root
+    mkdir /mnt/user/0/emulated/0 0755 root root
+
+    # Prepare directories for pass through processes
+    mkdir /mnt/pass_through 0755 root root
+    mkdir /mnt/pass_through/0 0755 root root
+    mkdir /mnt/pass_through/0/self 0755 root root
+    mkdir /mnt/pass_through/0/emulated 0755 root root
+    mkdir /mnt/pass_through/0/emulated/0 0755 root root
+
     mkdir /mnt/expand 0771 system system
     mkdir /mnt/appfuse 0711 root root
 
@@ -225,6 +292,16 @@
     chmod 0664 /dev/cpuset/restricted/tasks
     chmod 0664 /dev/cpuset/tasks
 
+    # freezer cgroup entries
+    mkdir /dev/freezer/frozen
+    write /dev/freezer/frozen/freezer.state FROZEN
+    chown system system /dev/freezer/cgroup.procs
+    chown system system /dev/freezer/frozen
+    chown system system /dev/freezer/frozen/freezer.state
+    chown system system /dev/freezer/frozen/cgroup.procs
+
+    chmod 0444 /dev/freezer/frozen/freezer.state
+
     # make the PSI monitor accessible to others
     chown system system /proc/pressure/memory
     chmod 0664 /proc/pressure/memory
@@ -267,12 +344,6 @@
 
     export DOWNLOAD_CACHE /data/cache
 
-    # set RLIMIT_NICE to allow priorities from 19 to -20
-    setrlimit nice 40 40
-
-    # Allow up to 32K FDs per process
-    setrlimit nofile 32768 32768
-
     # This allows the ledtrig-transient properties to be created here so
     # that they can be chown'd to system:system later on boot
     write /sys/class/leds/vibrator/trigger "transient"
@@ -288,8 +359,15 @@
     chown system system /sys/power/wakeup_count
     chmod 0660 /sys/power/state
 
+    chown radio wakelock /sys/power/wake_lock
+    chown radio wakelock /sys/power/wake_unlock
+    chmod 0660 /sys/power/wake_lock
+    chmod 0660 /sys/power/wake_unlock
+
     # Start logd before any other services run to ensure we capture all of their logs.
     start logd
+    # Start lmkd before any other services run so that it can register them
+    start lmkd
 
     # Start essential services.
     start servicemanager
@@ -355,9 +433,6 @@
     # Once everything is setup, no need to modify /.
     # The bind+remount combination allows this to work in containers.
     mount rootfs rootfs / remount bind ro nodev
-    # Mount default storage into root namespace
-    mount none /mnt/runtime/default /storage bind rec
-    mount none none /storage slave rec
 
     # Make sure /sys/kernel/debug (if present) is labeled properly
     # Note that tracefs may be mounted under debug, so we need to cross filesystems
@@ -402,6 +477,8 @@
     mkdir /metadata/vold
     chmod 0700 /metadata/vold
     mkdir /metadata/password_slots 0771 root system
+    mkdir /metadata/ota 0700 root system
+    mkdir /metadata/ota/snapshots 0700 root system
 
     mkdir /metadata/apex 0700 root system
     mkdir /metadata/apex/sessions 0700 root system
@@ -417,7 +494,6 @@
     mark_post_data
 
     # Start checkpoint before we touch data
-    start vold
     exec - system system -- /system/bin/vdc checkpoint prepareCheckpoint
 
     # We chown/chmod /data again so because mount is run as root + defaults
@@ -431,29 +507,26 @@
 
     # Start bootcharting as soon as possible after the data partition is
     # mounted to collect more data.
-    mkdir /data/bootchart 0755 shell shell
+    mkdir /data/bootchart 0755 shell shell encryption=Require
     bootchart start
 
-    # Load fsverity keys. This needs to happen before apexd, as post-install of
-    # APEXes may rely on keys.
-    exec -- /system/bin/fsverity_init
-
     # Make sure that apexd is started in the default namespace
     enter_default_mount_ns
 
     # /data/apex is now available. Start apexd to scan and activate APEXes.
-    mkdir /data/apex 0750 root system
+    mkdir /data/apex 0750 root system encryption=None
     mkdir /data/apex/active 0750 root system
     mkdir /data/apex/backup 0700 root system
+    mkdir /data/apex/hashtree 0700 root system
     mkdir /data/apex/sessions 0700 root system
-    mkdir /data/app-staging 0750 system system
+    mkdir /data/app-staging 0750 system system encryption=None
     start apexd
 
     # Avoid predictable entropy pool. Carry over entropy from previous boot.
     copy /data/system/entropy.dat /dev/urandom
 
     # create basic filesystem structure
-    mkdir /data/misc 01771 system misc
+    mkdir /data/misc 01771 system misc encryption=Require
     mkdir /data/misc/recovery 0770 system log
     copy /data/misc/recovery/ro.build.fingerprint /data/misc/recovery/ro.build.fingerprint.1
     chmod 0440 /data/misc/recovery/ro.build.fingerprint.1
@@ -482,6 +555,7 @@
     mkdir /data/misc/sms 0770 system radio
     mkdir /data/misc/carrierid 0770 system radio
     mkdir /data/misc/apns 0770 system radio
+    mkdir /data/misc/emergencynumberdb 0770 system radio
     mkdir /data/misc/zoneinfo 0775 system system
     mkdir /data/misc/network_watchlist 0774 system system
     mkdir /data/misc/textclassifier 0771 system system
@@ -494,10 +568,9 @@
     mkdir /data/misc/ethernet 0770 system system
     mkdir /data/misc/dhcp 0770 dhcp dhcp
     mkdir /data/misc/user 0771 root root
-    mkdir /data/misc/perfprofd 0775 root root
     # give system access to wpa_supplicant.conf for backup and restore
     chmod 0660 /data/misc/wifi/wpa_supplicant.conf
-    mkdir /data/local 0751 root root
+    mkdir /data/local 0751 root root encryption=Require
     mkdir /data/misc/media 0700 media media
     mkdir /data/misc/audioserver 0700 audioserver audioserver
     mkdir /data/misc/cameraserver 0700 cameraserver cameraserver
@@ -514,99 +587,136 @@
     mkdir /data/misc/profiles/ref 0771 system system
     mkdir /data/misc/profman 0770 system shell
     mkdir /data/misc/gcov 0770 root root
+    mkdir /data/misc/installd 0700 root root
+    mkdir /data/misc/apexdata 0700 root root
+    mkdir /data/misc/apexrollback 0700 root root
 
-    mkdir /data/preloads 0775 system system
+    mkdir /data/preloads 0775 system system encryption=None
 
-    mkdir /data/vendor 0771 root root
-    mkdir /data/vendor_ce 0771 root root
-    mkdir /data/vendor_de 0771 root root
+    mkdir /data/vendor 0771 root root encryption=Require
+    mkdir /data/vendor_ce 0771 root root encryption=None
+    mkdir /data/vendor_de 0771 root root encryption=None
     mkdir /data/vendor/hardware 0771 root root
 
     # For security reasons, /data/local/tmp should always be empty.
     # Do not place files or directories in /data/local/tmp
     mkdir /data/local/tmp 0771 shell shell
     mkdir /data/local/traces 0777 shell shell
-    mkdir /data/data 0771 system system
-    mkdir /data/app-private 0771 system system
-    mkdir /data/app-ephemeral 0771 system system
-    mkdir /data/app-asec 0700 root root
-    mkdir /data/app-lib 0771 system system
-    mkdir /data/app 0771 system system
-    mkdir /data/property 0700 root root
-    mkdir /data/tombstones 0771 system system
+    mkdir /data/data 0771 system system encryption=None
+    mkdir /data/app-private 0771 system system encryption=Require
+    mkdir /data/app-ephemeral 0771 system system encryption=Require
+    mkdir /data/app-asec 0700 root root encryption=Require
+    mkdir /data/app-lib 0771 system system encryption=Require
+    mkdir /data/app 0771 system system encryption=Require
+    mkdir /data/property 0700 root root encryption=Require
+    mkdir /data/tombstones 0771 system system encryption=Require
     mkdir /data/vendor/tombstones 0771 root root
     mkdir /data/vendor/tombstones/wifi 0771 wifi wifi
 
     # create dalvik-cache, so as to enforce our permissions
-    mkdir /data/dalvik-cache 0771 root root
+    mkdir /data/dalvik-cache 0771 root root encryption=Require
     # create the A/B OTA directory, so as to enforce our permissions
-    mkdir /data/ota 0771 root root
+    mkdir /data/ota 0771 root root encryption=Require
 
     # create the OTA package directory. It will be accessed by GmsCore (cache
     # group), update_engine and update_verifier.
-    mkdir /data/ota_package 0770 system cache
+    mkdir /data/ota_package 0770 system cache encryption=Require
 
     # create resource-cache and double-check the perms
-    mkdir /data/resource-cache 0771 system system
+    mkdir /data/resource-cache 0771 system system encryption=Require
     chown system system /data/resource-cache
     chmod 0771 /data/resource-cache
 
     # create the lost+found directories, so as to enforce our permissions
-    mkdir /data/lost+found 0770 root root
+    mkdir /data/lost+found 0770 root root encryption=None
 
     # create directory for DRM plug-ins - give drm the read/write access to
     # the following directory.
-    mkdir /data/drm 0770 drm drm
+    mkdir /data/drm 0770 drm drm encryption=Require
 
     # create directory for MediaDrm plug-ins - give drm the read/write access to
     # the following directory.
-    mkdir /data/mediadrm 0770 mediadrm mediadrm
+    mkdir /data/mediadrm 0770 mediadrm mediadrm encryption=Require
 
-    mkdir /data/anr 0775 system system
+    mkdir /data/anr 0775 system system encryption=Require
 
     # NFC: create data/nfc for nv storage
-    mkdir /data/nfc 0770 nfc nfc
+    mkdir /data/nfc 0770 nfc nfc encryption=Require
     mkdir /data/nfc/param 0770 nfc nfc
 
     # Create all remaining /data root dirs so that they are made through init
     # and get proper encryption policy installed
-    mkdir /data/backup 0700 system system
-    mkdir /data/ss 0700 system system
+    mkdir /data/backup 0700 system system encryption=Require
+    mkdir /data/ss 0700 system system encryption=Require
 
-    mkdir /data/system 0775 system system
+    mkdir /data/system 0775 system system encryption=Require
     mkdir /data/system/dropbox 0700 system system
     mkdir /data/system/heapdump 0700 system system
     mkdir /data/system/users 0775 system system
 
-    mkdir /data/system_de 0770 system system
-    mkdir /data/system_ce 0770 system system
+    mkdir /data/system_de 0770 system system encryption=None
+    mkdir /data/system_ce 0770 system system encryption=None
 
-    mkdir /data/misc_de 01771 system misc
-    mkdir /data/misc_ce 01771 system misc
+    mkdir /data/misc_de 01771 system misc encryption=None
+    mkdir /data/misc_ce 01771 system misc encryption=None
 
-    mkdir /data/user 0711 system system
-    mkdir /data/user_de 0711 system system
-    symlink /data/data /data/user/0
+    mkdir /data/user 0711 system system encryption=None
+    mkdir /data/user_de 0711 system system encryption=None
 
-    mkdir /data/media 0770 media_rw media_rw
-    mkdir /data/media/obb 0770 media_rw media_rw
+    # Unlink /data/user/0 if we previously symlink it to /data/data
+    rm /data/user/0
 
-    mkdir /data/cache 0770 system cache
+    # Bind mount /data/user/0 to /data/data
+    mkdir /data/user/0 0700 system system encryption=None
+    mount none /data/data /data/user/0 bind rec
+
+    # Special-case /data/media/obb per b/64566063
+    mkdir /data/media 0770 media_rw media_rw encryption=None
+    mkdir /data/media/obb 0770 media_rw media_rw encryption=Attempt
+
+    # A tmpfs directory, which will contain all apps CE DE data directory that
+    # bind mount from the original source.
+    chown root root /data_mirror
+    chmod 0700 /data_mirror
+    mount tmpfs tmpfs /data_mirror mode=0700,uid=0,gid=1000 nodev noexec nosuid
+    restorecon /data_mirror
+    mkdir /data_mirror/data_ce 0700 root root
+    mkdir /data_mirror/data_de 0700 root root
+
+    # Create CE and DE data directory for default volume
+    mkdir /data_mirror/data_ce/null 0700 root root
+    mkdir /data_mirror/data_de/null 0700 root root
+
+    # Bind mount CE and DE data directory to mirror's default volume directory
+    mount none /data/user /data_mirror/data_ce/null bind rec
+    mount none /data/user_de /data_mirror/data_de/null bind rec
+
+    mkdir /data/cache 0770 system cache encryption=Require
     mkdir /data/cache/recovery 0770 system cache
     mkdir /data/cache/backup_stage 0700 system system
     mkdir /data/cache/backup 0700 system system
 
+    # Delete these if need be, per b/139193659
+    mkdir /data/rollback 0700 system system encryption=DeleteIfNecessary
+    mkdir /data/rollback-observer 0700 system system encryption=DeleteIfNecessary
+
+    # Create root dir for Incremental Service
+    mkdir /data/incremental 0770 system system encryption=None
+
     # Wait for apexd to finish activating APEXes before starting more processes.
     wait_for_prop apexd.status ready
-    parse_apex_configs
+    perform_apex_config
+
+    exec_start derive_sdk
 
     init_user0
 
     # Set SELinux security contexts on upgrade or policy update.
     restorecon --recursive --skip-ce /data
 
-    # Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
-    exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo
+    # Check any timezone data in /data is newer than the copy in the time zone data
+    # module, delete if not.
+    exec - system system -- /system/bin/tzdatacheck /apex/com.android.tzdata/etc/tz /data/misc/zoneinfo
 
     # If there is no post-fs-data action in the init.<device>.rc file, you
     # must uncomment this line, otherwise encrypted filesystems
@@ -623,6 +733,22 @@
     chown root system /dev/fscklogs/log
     chmod 0770 /dev/fscklogs/log
 
+# Switch between sdcardfs and FUSE depending on persist property
+# TODO: Move this to ro property before launch because FDE devices
+# interact with persistent properties differently during boot
+on zygote-start && property:persist.sys.fuse=true
+  # Mount default storage into root namespace
+  mount none /mnt/user/0 /storage bind rec
+  mount none none /storage slave rec
+on zygote-start && property:persist.sys.fuse=false
+  # Mount default storage into root namespace
+  mount none /mnt/runtime/default /storage bind rec
+  mount none none /storage slave rec
+on zygote-start && property:persist.sys.fuse=""
+  # Mount default storage into root namespace
+  mount none /mnt/runtime/default /storage bind rec
+  mount none none /storage slave rec
+
 # It is recommended to put unnecessary data/ initialization from post-fs-data
 # to start-zygote in device's init.rc to unblock zygote start.
 on zygote-start && property:ro.crypto.state=unencrypted
@@ -682,17 +808,13 @@
     write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200
     write /sys/fs/f2fs/${dev.mnt.blk.data}/gc_urgent_sleep_time 50
 
+    # limit discard size to 128MB in order to avoid long IO latency
+    # for filesystem tuning first (dm or sda)
+    # Note that, if dm-<num> is used, sda/mmcblk0 should be tuned in vendor/init.rc
+    write /sys/devices/virtual/block/${dev.mnt.blk.data}/queue/discard_max_bytes 134217728
+
     # Permissions for System Server and daemons.
-    chown radio system /sys/android_power/state
-    chown radio system /sys/android_power/request_state
-    chown radio system /sys/android_power/acquire_full_wake_lock
-    chown radio system /sys/android_power/acquire_partial_wake_lock
-    chown radio system /sys/android_power/release_wake_lock
     chown system system /sys/power/autosleep
-    chown radio wakelock /sys/power/wake_lock
-    chown radio wakelock /sys/power/wake_unlock
-    chmod 0660 /sys/power/wake_lock
-    chmod 0660 /sys/power/wake_unlock
 
     chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate
     chmod 0660 /sys/devices/system/cpu/cpufreq/interactive/timer_rate
@@ -755,6 +877,9 @@
 
     class_start core
 
+    # Requires keystore (currently a core service) to be ready first.
+    exec -- /system/bin/fsverity_init
+
 on nonencrypted
     class_start main
     class_start late_start
@@ -799,7 +924,7 @@
     bootchart stop
     # Setup per_boot directory so other .rc could start to use it on boot_completed
     exec - system system -- /bin/rm -rf /data/per_boot
-    mkdir /data/per_boot 0700 system system
+    mkdir /data/per_boot 0700 system system encryption=Require key=per_boot_ref
 
 # system server cannot write to /proc/sys files,
 # and chown/chmod does not work for /proc/sys/ entries.
@@ -847,8 +972,34 @@
     chmod 0773 /data/misc/trace
     # Give reads to anyone for the window trace folder on debug builds.
     chmod 0775 /data/misc/wmtrace
+
+on init && property:ro.debuggable=1
     start console
 
-service flash_recovery /system/bin/install-recovery.sh
-    class main
-    oneshot
+on userspace-reboot-requested
+  # TODO(b/135984674): reset all necessary properties here.
+  setprop sys.boot_completed ""
+  setprop sys.init.updatable_crashing ""
+  setprop sys.init.updatable_crashing_process_name ""
+  setprop apexd.status ""
+  setprop sys.user.0.ce_available ""
+  setprop sys.shutdown.requested ""
+
+on userspace-reboot-fs-remount
+  # Make sure that vold is running.
+  # This is mostly a precaution measure in case vold for some reason wasn't running when
+  # userspace reboot was initiated.
+  start vold
+  exec - system system -- /system/bin/vdc checkpoint resetCheckpoint
+  exec - system system -- /system/bin/vdc checkpoint markBootAttempt
+  remount_userdata
+
+on userspace-reboot-resume
+  trigger userspace-reboot-fs-remount
+  trigger post-fs-data
+  trigger zygote-start
+  trigger early-boot
+  trigger boot
+
+on property:sys.boot_completed=1 && property:sys.init.userspace_reboot.in_progress=1
+  finish_userspace_reboot
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index b6cba90..02d34ba 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -9,16 +9,19 @@
     chown system system /sys/class/android_usb/android0/f_rndis/ethaddr
     chmod 0660 /sys/class/android_usb/android0/f_rndis/ethaddr
     mkdir /data/misc/adb 02750 system shell
-    mkdir /data/adb 0700 root root
+    mkdir /data/adb 0700 root root encryption=Require
 
 # adbd is controlled via property triggers in init.<platform>.usb.rc
 service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
     class core
     socket adbd seqpacket 660 system system
     disabled
+    updatable
     seclabel u:r:adbd:s0
 
-on boot
+# Set default value on sys.usb.configfs early in boot sequence. It will be
+# overridden in `on boot` action of init.hardware.rc.
+on init
     setprop sys.usb.configfs 0
 
 # Used to disable USB when switching states
@@ -132,3 +135,8 @@
 on property:sys.usb.typec.power_role=sink
     write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power_role}
     setprop sys.usb.typec.state ${sys.usb.typec.power_role}
+
+on userspace-reboot-requested
+  setprop sys.usb.config ""
+  setprop sys.usb.configfs ""
+  setprop sys.usb.state ""
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index bf3fb42..9adbcba 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -5,7 +5,6 @@
     group root readproc reserved_disk
     socket zygote stream 660 root system
     socket usap_pool_primary stream 660 root system
-    onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
     onrestart restart cameraserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 1bab588..f6149c9 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -5,7 +5,6 @@
     group root readproc reserved_disk
     socket zygote stream 660 root system
     socket usap_pool_primary stream 660 root system
-    onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
     onrestart restart cameraserver
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 6fa210a..0e69b16 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -5,7 +5,6 @@
     group root readproc reserved_disk
     socket zygote stream 660 root system
     socket usap_pool_primary stream 660 root system
-    onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
     onrestart restart cameraserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 48461ec..3e80168 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -5,7 +5,6 @@
     group root readproc reserved_disk
     socket zygote stream 660 root system
     socket usap_pool_primary stream 660 root system
-    onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
     onrestart restart cameraserver
diff --git a/rootdir/ld_config_backward_compatibility_check.py b/rootdir/ld_config_backward_compatibility_check.py
deleted file mode 100755
index 1a27578..0000000
--- a/rootdir/ld_config_backward_compatibility_check.py
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-import glob
-import os.path
-import re
-import sys
-
-PREBUILTS_VNDK_DIR = "prebuilts/vndk"
-VENDOR_DIRECTORIES = ('/vendor', '/odm')
-
-def find_latest_vndk_snapshot_version():
-  """Returns latest vndk snapshot version in current source tree.
-  It will skip the test if the snapshot directories are not found.
-
-  Returns:
-    latest_version: string
-  """
-  vndk_dir_list = glob.glob(PREBUILTS_VNDK_DIR + "/v*")
-  if not vndk_dir_list:
-    """Exit without error because we may have source trees that do not include
-    VNDK snapshot directories in it.
-    """
-    sys.exit(0)
-  vndk_ver_list = [re.match(r".*/v(\d+)", vndk_dir).group(1)
-                                          for vndk_dir in vndk_dir_list]
-  latest_version = max(vndk_ver_list)
-  if latest_version == '27':
-    """Exit without error because VNDK v27 is not using ld.config.txt template
-    """
-    sys.exit(0)
-  return latest_version
-
-def get_vendor_configuration(ld_config_file):
-  """Reads the ld.config.txt file to parse the namespace configurations.
-  It finds the configurations that include vendor directories.
-
-  Args:
-    ld_config_file: string, path (relative to build top) of the ld.config.txt
-                    file.
-  Returns:
-    configs: dict{string:[string]}, dictionary of namespace configurations.
-             it has 'section + property' names as keys and the directory list
-             as values.
-  """
-  try:
-    conf_file = open(ld_config_file)
-  except IOError:
-    print("error: could not read %s" % ld_config_file)
-    sys.exit(1)
-
-  configs = dict()
-  current_section = None
-
-  with conf_file:
-    for line in conf_file:
-      # ignore comments
-      found = line.find('#')
-      if found != -1:
-        line = line[:found]
-      line = line.strip()
-      if not line:
-        continue
-
-      if line[0] == '[' and line[-1] == ']':
-        # new section started
-        current_section = line[1:-1]
-        continue
-
-      if current_section == None:
-        continue
-
-      found = line.find('+=')
-      opr_len = 2
-      if found == -1:
-        found = line.find('=')
-        opr_len = 1
-      if found == -1:
-        continue
-
-      namespace = line[:found].strip()
-      if not namespace.endswith(".paths"):
-        # check ".paths" only
-        continue
-      namespace = '[' + current_section + ']' + namespace
-      values = line[found + opr_len:].strip()
-      directories = values.split(':')
-
-      for directory in directories:
-        if any(vendor_dir in directory for vendor_dir in VENDOR_DIRECTORIES):
-          if namespace in configs:
-            configs[namespace].append(directory)
-          else:
-            configs[namespace] = [directory]
-
-  return configs
-
-def get_snapshot_config(version):
-  """Finds the ld.config.{version}.txt file from the VNDK snapshot directory.
-  In the vndk prebuilt directory (prebuilts/vndk/v{version}), it searches
-  {arch}/configs/ld.config.{version}.txt file, where {arch} is one of ('arm64',
-  'arm', 'x86_64', 'x86').
-
-  Args:
-    version: string, the VNDK snapshot version to search.
-  Returns:
-    ld_config_file: string, relative path to ld.config.{version}.txt
-  """
-  arch_list = ('arm64', 'arm', 'x86_64', 'x86')
-  for arch in arch_list:
-    ld_config_file = (PREBUILTS_VNDK_DIR
-                + "/v{0}/{1}/configs/ld.config.{0}.txt".format(version, arch))
-    if os.path.isfile(ld_config_file):
-      return ld_config_file
-  print("error: cannot find ld.config.{0}.txt file in snapshot v{0}"
-                                                        .format(version))
-  sys.exit(1)
-
-def check_backward_compatibility(ld_config, vndk_snapshot_version):
-  """Checks backward compatibility for current ld.config.txt file with the
-  old ld.config.txt file. If any of the vendor directories in the old namespace
-  configurations are missing, the test will fail. It is allowed to have new
-  vendor directories in current ld.config.txt file.
-
-  Args:
-    ld_config: string, relative path to current ld.config.txt file.
-    vndk_snapshot_version: string, the VNDK snapshot version that has an old
-                           ld.config.txt file to compare.
-  Returns:
-    result: bool, True if the current configuration is backward compatible.
-  """
-  current_config = get_vendor_configuration(ld_config)
-  old_config = get_vendor_configuration(
-                                get_snapshot_config(vndk_snapshot_version))
-  for namespace in old_config:
-    if namespace not in current_config:
-      print("error: cannot find %s which was provided in ld.config.%s.txt"
-                                        % (namespace, vndk_snapshot_version))
-      return False
-    for path in old_config[namespace]:
-      if not path in current_config[namespace]:
-        print("error: %s for %s in ld.config.%s.txt are missing in %s"
-                % (path, namespace, vndk_snapshot_version, ld_config))
-        return False
-  return True
-
-def main():
-  if len(sys.argv) != 2:
-    print ("Usage: %s target_ld_config_txt_file_name" % sys.argv[0])
-    sys.exit(1)
-
-  latest_vndk_snapshot_version = find_latest_vndk_snapshot_version()
-  if not check_backward_compatibility(sys.argv[1],
-                                          latest_vndk_snapshot_version):
-    print("error: %s has backward incompatible changes to old "
-          "vendor partition." % sys.argv[1])
-    sys.exit(1)
-
-  # Current ld.config.txt file is backward compatible
-  sys.exit(0)
-
-if __name__ == '__main__':
-  main()
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 451f5ad..9c2cdf2 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -33,7 +33,7 @@
 /dev/urandom              0666   root       root
 # Make HW RNG readable by group system to let EntropyMixer read it.
 /dev/hw_random            0440   root       system
-/dev/ashmem               0666   root       root
+/dev/ashmem*              0666   root       root
 /dev/binder               0666   root       root
 /dev/hwbinder             0666   root       root
 /dev/vndbinder            0666   root       root
diff --git a/rootdir/update_and_install_ld_config.mk b/rootdir/update_and_install_ld_config.mk
deleted file mode 100644
index 1282868..0000000
--- a/rootdir/update_and_install_ld_config.mk
+++ /dev/null
@@ -1,185 +0,0 @@
-#####################################################################
-# Builds linker config file, ld.config.txt, from the specified template
-# under $(LOCAL_PATH)/etc/*.
-#
-# Inputs:
-#   (expected to follow an include of $(BUILD_SYSTEM)/base_rules.mk)
-#   ld_config_template: template linker config file to use,
-#                       e.g. $(LOCAL_PATH)/etc/ld.config.txt
-#   vndk_version: version of the VNDK library lists used to update the
-#                 template linker config file, e.g. 28
-#   lib_list_from_prebuilts: should be set to 'true' if the VNDK library
-#                            lists should be read from /prebuilts/vndk/*
-#   libz_is_llndk: should be set to 'true' if libz must be included in
-#                  llndk and not in vndk-sp
-# Outputs:
-#   Builds and installs ld.config.$VER.txt or ld.config.vndk_lite.txt
-#####################################################################
-
-# Read inputs
-ld_config_template := $(strip $(ld_config_template))
-check_backward_compatibility := $(strip $(check_backward_compatibility))
-vndk_version := $(strip $(vndk_version))
-lib_list_from_prebuilts := $(strip $(lib_list_from_prebuilts))
-libz_is_llndk := $(strip $(libz_is_llndk))
-
-my_vndk_use_core_variant := $(TARGET_VNDK_USE_CORE_VARIANT)
-ifeq ($(lib_list_from_prebuilts),true)
-my_vndk_use_core_variant := false
-endif
-
-compatibility_check_script := \
-  $(LOCAL_PATH)/ld_config_backward_compatibility_check.py
-intermediates_dir := $(call intermediates-dir-for,ETC,$(LOCAL_MODULE))
-library_lists_dir := $(intermediates_dir)
-ifeq ($(lib_list_from_prebuilts),true)
-  library_lists_dir := prebuilts/vndk/v$(vndk_version)/$(TARGET_ARCH)/configs
-endif
-
-llndk_libraries_file := $(library_lists_dir)/llndk.libraries.$(vndk_version).txt
-vndksp_libraries_file := $(library_lists_dir)/vndksp.libraries.$(vndk_version).txt
-vndkcore_libraries_file := $(library_lists_dir)/vndkcore.libraries.txt
-vndkprivate_libraries_file := $(library_lists_dir)/vndkprivate.libraries.txt
-ifeq ($(my_vndk_use_core_variant),true)
-vndk_using_core_variant_libraries_file := $(library_lists_dir)/vndk_using_core_variant.libraries.$(vndk_version).txt
-endif
-
-sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
-  $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
-  $(HWADDRESS_SANITIZER_RUNTIME_LIBRARY) \
-  $(UBSAN_RUNTIME_LIBRARY) \
-  $(TSAN_RUNTIME_LIBRARY) \
-  $(2ND_ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
-  $(2ND_HWADDRESS_SANITIZER_RUNTIME_LIBRARY) \
-  $(2ND_UBSAN_RUNTIME_LIBRARY) \
-  $(2ND_TSAN_RUNTIME_LIBRARY)))
-# If BOARD_VNDK_VERSION is not defined, VNDK version suffix will not be used.
-vndk_version_suffix := $(if $(vndk_version),-$(vndk_version))
-
-ifneq ($(lib_list_from_prebuilts),true)
-ifeq ($(libz_is_llndk),true)
-  llndk_libraries_list := $(LLNDK_LIBRARIES) libz
-  vndksp_libraries_list := $(filter-out libz,$(VNDK_SAMEPROCESS_LIBRARIES))
-else
-  llndk_libraries_list := $(LLNDK_LIBRARIES)
-  vndksp_libraries_list := $(VNDK_SAMEPROCESS_LIBRARIES)
-endif
-
-# $(1): list of libraries
-# $(2): output file to write the list of libraries to
-define write-libs-to-file
-$(2): PRIVATE_LIBRARIES := $(1)
-$(2):
-	echo -n > $$@ && $$(foreach lib,$$(PRIVATE_LIBRARIES),echo $$(lib).so >> $$@;)
-endef
-$(eval $(call write-libs-to-file,$(llndk_libraries_list),$(llndk_libraries_file)))
-$(eval $(call write-libs-to-file,$(vndksp_libraries_list),$(vndksp_libraries_file)))
-$(eval $(call write-libs-to-file,$(VNDK_CORE_LIBRARIES),$(vndkcore_libraries_file)))
-$(eval $(call write-libs-to-file,$(VNDK_PRIVATE_LIBRARIES),$(vndkprivate_libraries_file)))
-ifeq ($(my_vndk_use_core_variant),true)
-$(eval $(call write-libs-to-file,$(VNDK_USING_CORE_VARIANT_LIBRARIES),$(vndk_using_core_variant_libraries_file)))
-endif
-endif # ifneq ($(lib_list_from_prebuilts),true)
-
-# Given a file with a list of libs, filter-out the VNDK private libraries
-# and write resulting list to a new file in "a:b:c" format
-#
-# $(1): libs file from which to filter-out VNDK private libraries
-# $(2): output file with the filtered list of lib names
-$(LOCAL_BUILT_MODULE): private-filter-out-private-libs = \
-  paste -sd ":" $(1) > $(2) && \
-  while read -r privatelib; do sed -i.bak "s/$$privatelib//" $(2) ; done < $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) && \
-  sed -i.bak -e 's/::\+/:/g ; s/^:\+// ; s/:\+$$//' $(2) && \
-  rm -f $(2).bak
-$(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES_FILE := $(llndk_libraries_file)
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SP_LIBRARIES_FILE := $(vndksp_libraries_file)
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_CORE_LIBRARIES_FILE := $(vndkcore_libraries_file)
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE := $(vndkprivate_libraries_file)
-$(LOCAL_BUILT_MODULE): PRIVATE_SANITIZER_RUNTIME_LIBRARIES := $(sanitizer_runtime_libraries)
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_VERSION_SUFFIX := $(vndk_version_suffix)
-$(LOCAL_BUILT_MODULE): PRIVATE_INTERMEDIATES_DIR := $(intermediates_dir)
-$(LOCAL_BUILT_MODULE): PRIVATE_COMP_CHECK_SCRIPT := $(compatibility_check_script)
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_VERSION_TAG := \#VNDK$(vndk_version)\#
-deps := $(llndk_libraries_file) $(vndksp_libraries_file) $(vndkcore_libraries_file) \
-  $(vndkprivate_libraries_file)
-ifeq ($(check_backward_compatibility),true)
-deps += $(compatibility_check_script)
-endif
-ifeq ($(my_vndk_use_core_variant),true)
-$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_USING_CORE_VARIANT_LIBRARIES_FILE := $(vndk_using_core_variant_libraries_file)
-deps += $(vndk_using_core_variant_libraries_file)
-endif
-
-$(LOCAL_BUILT_MODULE): $(ld_config_template) $(deps)
-	@echo "Generate: $< -> $@"
-ifeq ($(check_backward_compatibility),true)
-	@echo "Checking backward compatibility..."
-	$(hide) $(PRIVATE_COMP_CHECK_SCRIPT) $<
-endif
-	@mkdir -p $(dir $@)
-	$(call private-filter-out-private-libs,$(PRIVATE_LLNDK_LIBRARIES_FILE),$(PRIVATE_INTERMEDIATES_DIR)/llndk_filtered)
-	$(hide) sed -e "s?%LLNDK_LIBRARIES%?$$(cat $(PRIVATE_INTERMEDIATES_DIR)/llndk_filtered)?g" $< >$@
-	$(call private-filter-out-private-libs,$(PRIVATE_VNDK_SP_LIBRARIES_FILE),$(PRIVATE_INTERMEDIATES_DIR)/vndksp_filtered)
-	$(hide) sed -i.bak -e "s?%VNDK_SAMEPROCESS_LIBRARIES%?$$(cat $(PRIVATE_INTERMEDIATES_DIR)/vndksp_filtered)?g" $@
-	$(call private-filter-out-private-libs,$(PRIVATE_VNDK_CORE_LIBRARIES_FILE),$(PRIVATE_INTERMEDIATES_DIR)/vndkcore_filtered)
-	$(hide) sed -i.bak -e "s?%VNDK_CORE_LIBRARIES%?$$(cat $(PRIVATE_INTERMEDIATES_DIR)/vndkcore_filtered)?g" $@
-
-ifeq ($(my_vndk_use_core_variant),true)
-	$(call private-filter-out-private-libs,$(PRIVATE_VNDK_USING_CORE_VARIANT_LIBRARIES_FILE),$(PRIVATE_INTERMEDIATES_DIR)/vndk_using_core_variant_filtered)
-	$(hide) sed -i.bak -e "s?%VNDK_IN_SYSTEM_NS%?,vndk_in_system?g" $@
-	$(hide) sed -i.bak -e "s?%VNDK_USING_CORE_VARIANT_LIBRARIES%?$$(cat $(PRIVATE_INTERMEDIATES_DIR)/vndk_using_core_variant_filtered)?g" $@
-else
-	$(hide) sed -i.bak -e "s?%VNDK_IN_SYSTEM_NS%??g" $@
-	# Unlike LLNDK or VNDK-SP, VNDK_USING_CORE_VARIANT_LIBRARIES can be nothing
-	# if TARGET_VNDK_USE_CORE_VARIANT is not set.  In this case, we need to remove
-	# the entire line in the linker config so that we are not left with a line
-	# like:
-	#   namespace.vndk.link.vndk_in_system.shared_libs =
-	$(hide) sed -i.bak -e 's?^.*= %VNDK_USING_CORE_VARIANT_LIBRARIES%$$??' $@
-endif
-
-	$(hide) echo -n > $(PRIVATE_INTERMEDIATES_DIR)/private_llndk && \
-	while read -r privatelib; \
-	do (grep $$privatelib $(PRIVATE_LLNDK_LIBRARIES_FILE) || true) >> $(PRIVATE_INTERMEDIATES_DIR)/private_llndk ; \
-	done < $(PRIVATE_VNDK_PRIVATE_LIBRARIES_FILE) && \
-	paste -sd ":" $(PRIVATE_INTERMEDIATES_DIR)/private_llndk | \
-	sed -i.bak -e "s?%PRIVATE_LLNDK_LIBRARIES%?$$(cat -)?g" $@
-
-	$(hide) sed -i.bak -e "s?%SANITIZER_RUNTIME_LIBRARIES%?$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES)?g" $@
-	$(hide) sed -i.bak -e "s?%VNDK_VER%?$(PRIVATE_VNDK_VERSION_SUFFIX)?g" $@
-	$(hide) sed -i.bak -e "s?%PRODUCT%?$(TARGET_COPY_OUT_PRODUCT)?g" $@
-ifeq ($(TARGET_COPY_OUT_PRODUCT),$(TARGET_COPY_OUT_PRODUCT_SERVICES))
-	# Remove lines containing %PRODUCT_SERVICES% (identical to the %PRODUCT% ones)
-	$(hide) sed -i.bak -e "\?%PRODUCT_SERVICES%?d" $@
-else
-	$(hide) sed -i.bak -e "s?%PRODUCT_SERVICES%?$(TARGET_COPY_OUT_PRODUCT_SERVICES)?g" $@
-endif
-	$(hide) sed -i.bak -e "s?^$(PRIVATE_VNDK_VERSION_TAG)??g" $@
-	$(hide) sed -i.bak "/^\#VNDK[0-9]\{2\}\#.*$$/d" $@
-	$(hide) rm -f $@.bak
-
-ld_config_template :=
-check_backward_compatibility :=
-vndk_version :=
-lib_list_from_prebuilts :=
-libz_is_llndk :=
-compatibility_check_script :=
-intermediates_dir :=
-library_lists_dir :=
-llndk_libraries_file :=
-vndksp_libraries_file :=
-vndkcore_libraries_file :=
-vndkprivate_libraries_file :=
-deps :=
-sanitizer_runtime_libraries :=
-vndk_version_suffix :=
-llndk_libraries_list :=
-vndksp_libraries_list :=
-write-libs-to-file :=
-
-ifeq ($(my_vndk_use_core_variant),true)
-vndk_using_core_variant_libraries_file :=
-vndk_using_core_variant_libraries_list :=
-endif
-
-my_vndk_use_core_variant :=
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index 2b35819..622de5b 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -315,7 +315,8 @@
         PLOG(ERROR) << "setting RLIMIT_NOFILE failed";
     }
 
-    while ((fs_read_atomic_int("/data/.layout_version", &fs_version) == -1) || (fs_version < 3)) {
+    while ((fs_read_atomic_int("/data/misc/installd/layout_version", &fs_version) == -1) ||
+           (fs_version < 3)) {
         LOG(ERROR) << "installd fs upgrade not yet complete; waiting...";
         sleep(1);
     }
diff --git a/demangle/.clang-format b/set-verity-state/.clang-format
similarity index 100%
copy from demangle/.clang-format
copy to set-verity-state/.clang-format
diff --git a/set-verity-state/Android.bp b/set-verity-state/Android.bp
new file mode 100644
index 0000000..cd8c8c5
--- /dev/null
+++ b/set-verity-state/Android.bp
@@ -0,0 +1,24 @@
+// Copyright 2019 The Android Open Source Project
+
+cc_binary {
+    name: "set-verity-state",
+    srcs: ["set-verity-state.cpp"],
+    shared_libs: [
+        "libbase",
+        "libcrypto",
+        "libcrypto_utils",
+        "libcutils",
+        "libfec",
+        "libfs_mgr",
+        "liblog",
+    ],
+    static_libs: [
+        "libavb_user",
+    ],
+
+    cflags: ["-Werror"],
+    symlinks: [
+        "enable-verity",
+        "disable-verity",
+    ],
+}
diff --git a/set-verity-state/set-verity-state.cpp b/set-verity-state/set-verity-state.cpp
new file mode 100644
index 0000000..0a26aba
--- /dev/null
+++ b/set-verity-state/set-verity-state.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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 <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libavb_user/libavb_user.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <fs_mgr.h>
+#include <fs_mgr_overlayfs.h>
+#include <fstab/fstab.h>
+#include <log/log_properties.h>
+
+#include "fec/io.h"
+
+#ifdef ALLOW_DISABLE_VERITY
+static const bool kAllowDisableVerity = true;
+#else
+static const bool kAllowDisableVerity = false;
+#endif
+
+using android::base::unique_fd;
+
+static void suggest_run_adb_root() {
+  if (getuid() != 0) printf("Maybe run adb root?\n");
+}
+
+static bool make_block_device_writable(const std::string& dev) {
+  unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
+  if (fd == -1) {
+    return false;
+  }
+
+  int OFF = 0;
+  bool result = (ioctl(fd.get(), BLKROSET, &OFF) != -1);
+  return result;
+}
+
+/* Turn verity on/off */
+static bool set_verity_enabled_state(const char* block_device, const char* mount_point,
+                                     bool enable) {
+  if (!make_block_device_writable(block_device)) {
+    printf("Could not make block device %s writable (%s).\n", block_device, strerror(errno));
+    return false;
+  }
+
+  fec::io fh(block_device, O_RDWR);
+
+  if (!fh) {
+    printf("Could not open block device %s (%s).\n", block_device, strerror(errno));
+    suggest_run_adb_root();
+    return false;
+  }
+
+  fec_verity_metadata metadata;
+
+  if (!fh.get_verity_metadata(metadata)) {
+    printf("Couldn't find verity metadata!\n");
+    return false;
+  }
+
+  if (!enable && metadata.disabled) {
+    printf("Verity already disabled on %s\n", mount_point);
+    return false;
+  }
+
+  if (enable && !metadata.disabled) {
+    printf("Verity already enabled on %s\n", mount_point);
+    return false;
+  }
+
+  if (!fh.set_verity_status(enable)) {
+    printf("Could not set verity %s flag on device %s with error %s\n",
+           enable ? "enabled" : "disabled", block_device, strerror(errno));
+    return false;
+  }
+
+  auto change = false;
+  errno = 0;
+  if (enable ? fs_mgr_overlayfs_teardown(mount_point, &change)
+             : fs_mgr_overlayfs_setup(nullptr, mount_point, &change)) {
+    if (change) {
+      printf("%s overlayfs for %s\n", enable ? "disabling" : "using", mount_point);
+    }
+  } else if (errno) {
+    int expected_errno = enable ? EBUSY : ENOENT;
+    if (errno != expected_errno) {
+      printf("Overlayfs %s for %s failed with error %s\n", enable ? "teardown" : "setup",
+             mount_point, strerror(errno));
+    }
+  }
+  printf("Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
+  return true;
+}
+
+/* Helper function to get A/B suffix, if any. If the device isn't
+ * using A/B the empty string is returned. Otherwise either "_a",
+ * "_b", ... is returned.
+ */
+static std::string get_ab_suffix() {
+  return android::base::GetProperty("ro.boot.slot_suffix", "");
+}
+
+static bool is_avb_device_locked() {
+  return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
+}
+
+static bool overlayfs_setup(bool enable) {
+  auto change = false;
+  errno = 0;
+  if (enable ? fs_mgr_overlayfs_teardown(nullptr, &change)
+             : fs_mgr_overlayfs_setup(nullptr, nullptr, &change)) {
+    if (change) {
+      printf("%s overlayfs\n", enable ? "disabling" : "using");
+    }
+  } else if (errno) {
+    printf("Overlayfs %s failed with error %s\n", enable ? "teardown" : "setup", strerror(errno));
+    suggest_run_adb_root();
+  }
+  return change;
+}
+
+/* Use AVB to turn verity on/off */
+static bool set_avb_verity_enabled_state(AvbOps* ops, bool enable_verity) {
+  std::string ab_suffix = get_ab_suffix();
+  bool verity_enabled;
+
+  if (is_avb_device_locked()) {
+    printf("Device is locked. Please unlock the device first\n");
+    return false;
+  }
+
+  if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) {
+    printf("Error getting verity state. Try adb root first?\n");
+    return false;
+  }
+
+  if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
+    printf("verity is already %s\n", verity_enabled ? "enabled" : "disabled");
+    return false;
+  }
+
+  if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) {
+    printf("Error setting verity\n");
+    return false;
+  }
+
+  overlayfs_setup(enable_verity);
+  printf("Successfully %s verity\n", enable_verity ? "enabled" : "disabled");
+  return true;
+}
+
+int main(int argc, char* argv[]) {
+  if (argc == 0) {
+    LOG(FATAL) << "set-verity-state called with empty argv";
+  }
+
+  std::optional<bool> enable_opt;
+  std::string procname = android::base::Basename(argv[0]);
+  if (procname == "enable-verity") {
+    enable_opt = true;
+  } else if (procname == "disable-verity") {
+    enable_opt = false;
+  }
+
+  if (!enable_opt.has_value()) {
+    if (argc != 2) {
+      printf("usage: %s [1|0]\n", argv[0]);
+      return 1;
+    }
+
+    if (strcmp(argv[1], "1") == 0) {
+      enable_opt = true;
+    } else if (strcmp(argv[1], "0") == 0) {
+      enable_opt = false;
+    } else {
+      printf("usage: %s [1|0]\n", argv[0]);
+      return 1;
+    }
+  }
+
+  bool enable = enable_opt.value();
+
+  bool any_changed = false;
+
+  // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+  // contract, androidboot.vbmeta.digest is set by the bootloader
+  // when using AVB).
+  bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
+
+  // If using AVB, dm-verity is used on any build so we want it to
+  // be possible to disable/enable on any build (except USER). For
+  // VB1.0 dm-verity is only enabled on certain builds.
+  if (!using_avb) {
+    if (!kAllowDisableVerity) {
+      printf("%s only works for userdebug builds\n", argv[0]);
+    }
+
+    if (!android::base::GetBoolProperty("ro.secure", false)) {
+      overlayfs_setup(enable);
+      printf("verity not enabled - ENG build\n");
+      return 0;
+    }
+  }
+
+  // Should never be possible to disable dm-verity on a USER build
+  // regardless of using AVB or VB1.0.
+  if (!__android_log_is_debuggable()) {
+    printf("verity cannot be disabled/enabled - USER build\n");
+    return 0;
+  }
+
+  if (using_avb) {
+    // Yep, the system is using AVB.
+    AvbOps* ops = avb_ops_user_new();
+    if (ops == nullptr) {
+      printf("Error getting AVB ops\n");
+      return 1;
+    }
+    if (set_avb_verity_enabled_state(ops, enable)) {
+      any_changed = true;
+    }
+    avb_ops_user_free(ops);
+  } else {
+    // Not using AVB - assume VB1.0.
+
+    // read all fstab entries at once from all sources
+    android::fs_mgr::Fstab fstab;
+    if (!android::fs_mgr::ReadDefaultFstab(&fstab)) {
+      printf("Failed to read fstab\n");
+      suggest_run_adb_root();
+      return 0;
+    }
+
+    // Loop through entries looking for ones that verity manages.
+    for (const auto& entry : fstab) {
+      if (entry.fs_mgr_flags.verify) {
+        if (set_verity_enabled_state(entry.blk_device.c_str(), entry.mount_point.c_str(), enable)) {
+          any_changed = true;
+        }
+      }
+    }
+  }
+  if (!any_changed) any_changed = overlayfs_setup(enable);
+
+  if (any_changed) {
+    printf("Now reboot your device for settings to take effect\n");
+  }
+
+  return 0;
+}
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 3bc3883..b5a5fb6 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -12,8 +12,9 @@
     required: [
         "auditctl",
         "awk",
+        "bc",
         "bzip2",
-        "grep",
+        "ldd",
         "logwrapper",
         "mini-keyctl",
         "mkshrc",
@@ -25,14 +26,13 @@
         "tcpdump",
         "toolbox",
         "toybox",
-        "unzip",
+        "ziptool",
     ],
 }
 
 phony {
     name: "shell_and_utilities_recovery",
     required: [
-        "grep.recovery",
         "sh.recovery",
         "toolbox.recovery",
         "toybox.recovery",
@@ -44,7 +44,6 @@
     name: "shell_and_utilities_vendor",
     required: [
         "awk_vendor",
-        "grep_vendor",
         "logwrapper_vendor",
         "mkshrc_vendor",
         "sh_vendor",
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index ffda3a5..d391cc1 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -211,3 +211,32 @@
 true truncate tty tunctl ulimit umount uname uniq unix2dos unlink
 unshare uptime usleep uudecode uuencode uuidgen vconfig vmstat watch
 wc which whoami xargs xxd yes zcat
+
+## Android R
+
+BSD: fsck\_msdos newfs\_msdos
+
+bzip2: bzcat bzip2 bunzip2
+
+one-true-awk: awk
+
+toolbox: getevent getprop setprop start stop
+
+toybox: acpi base64 basename bc blkid blockdev cal cat chattr chcon chgrp
+chmod chown chroot chrt cksum clear cmp comm cp cpio cut date dd df
+diff dirname dmesg dos2unix du echo egrep env expand expr fallocate
+false fgrep file find flock fmt free freeramdisk fsfreeze getconf
+getenforce getfattr grep groups gunzip gzip head help hostname hwclock
+i2cdetect i2cdump i2cget i2cset iconv id ifconfig inotifyd insmod
+install ionice iorenice iotop kill killall ln load\_policy log logname
+losetup ls lsattr lsmod lsof lspci lsusb makedevs md5sum microcom
+mkdir mkfifo mknod mkswap mktemp modinfo modprobe more mount mountpoint
+mv nbd-client nc netcat netstat nice nl nohup nproc nsenter od partprobe
+paste patch pgrep pidof ping ping6 pivot\_root pkill pmap printenv
+printf prlimit ps pwd pwdx readlink realpath renice restorecon rev
+rfkill rm rmdir rmmod runcon sed sendevent seq setenforce setfattr
+setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep sort split
+stat strings stty swapoff swapon sync sysctl tac tail tar taskset tee
+time timeout top touch tr traceroute traceroute6 true truncate tty tunctl
+ulimit umount uname uniq unix2dos unlink unshare uptime usleep uudecode
+uuencode uuidgen vconfig vmstat watch wc which whoami xargs xxd yes zcat
diff --git a/storaged/Android.bp b/storaged/Android.bp
index 733b60f..cc19481 100644
--- a/storaged/Android.bp
+++ b/storaged/Android.bp
@@ -24,8 +24,6 @@
         "libbinder",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libprotobuf-cpp-lite",
         "libsysutils",
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 6897663..1d934a2 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -164,8 +164,10 @@
 }
 
 void storaged_t::add_user_ce(userid_t user_id) {
-    load_proto(user_id);
-    proto_loaded[user_id] = true;
+    if (!proto_loaded[user_id]) {
+        load_proto(user_id);
+        proto_loaded[user_id] = true;
+    }
 }
 
 void storaged_t::remove_user_ce(userid_t user_id) {
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index ca2421b..6668cf3 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -41,7 +41,6 @@
 using android::hardware::health::V2_0::StorageInfo;
 
 const string emmc_info_t::emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
-const string emmc_info_t::emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd";
 const char* emmc_info_t::emmc_ver_str[9] = {
     "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1"
 };
@@ -62,10 +61,8 @@
     if (healthService != nullptr) {
         return new health_storage_info_t(healthService);
     }
-    if (FileExists(emmc_info_t::emmc_sysfs) ||
-        FileExists(emmc_info_t::emmc_debugfs)) {
-        return new emmc_info_t;
-    }
+    if (FileExists(emmc_info_t::emmc_sysfs)) return new emmc_info_t;
+
     if (FileExists(ufs_info_t::health_file)) {
         return new ufs_info_t;
     }
@@ -241,8 +238,7 @@
 
 void emmc_info_t::report()
 {
-    if (!report_sysfs() && !report_debugfs())
-        return;
+    if (!report_sysfs()) return;
 
     publish();
 }
@@ -284,54 +280,6 @@
     return true;
 }
 
-namespace {
-
-const size_t EXT_CSD_FILE_MIN_SIZE = 1024;
-/* 2 characters in string for each byte */
-const size_t EXT_CSD_REV_IDX = 192 * 2;
-const size_t EXT_PRE_EOL_INFO_IDX = 267 * 2;
-const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * 2;
-const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * 2;
-
-} // namespace
-
-bool emmc_info_t::report_debugfs()
-{
-    string buffer;
-    uint16_t rev = 0;
-
-    if (!ReadFileToString(emmc_debugfs, &buffer) ||
-        buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
-        return false;
-    }
-
-    string str = buffer.substr(EXT_CSD_REV_IDX, 2);
-    if (!ParseUint(str, &rev) ||
-        rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
-        return false;
-    }
-
-    version = "emmc ";
-    version += emmc_ver_str[rev];
-
-    str = buffer.substr(EXT_PRE_EOL_INFO_IDX, 2);
-    if (!ParseUint(str, &eol)) {
-        return false;
-    }
-
-    str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, 2);
-    if (!ParseUint(str, &lifetime_a)) {
-        return false;
-    }
-
-    str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, 2);
-    if (!ParseUint(str, &lifetime_b)) {
-        return false;
-    }
-
-    return true;
-}
-
 void ufs_info_t::report()
 {
     string buffer;
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 1f852ff..4ca5f5a 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -1,14 +1,10 @@
 cc_defaults {
     name: "toolbox_defaults",
-
     cflags: [
         "-Werror",
         "-Wno-unused-parameter",
         "-Wno-unused-const-variable",
         "-D_FILE_OFFSET_BITS=64",
-        "-DWITHOUT_NLS",
-        "-DWITHOUT_BZ2",
-        "-DWITHOUT_GZIP",
     ],
 }
 
@@ -28,6 +24,9 @@
         "toolbox.c",
         "getevent.c",
         "getprop.cpp",
+        "modprobe.cpp",
+        "setprop.cpp",
+        "start.cpp",
     ],
     generated_headers: [
         "toolbox_input_labels",
@@ -35,11 +34,18 @@
     shared_libs: [
         "libbase",
     ],
-    static_libs: ["libpropertyinfoparser"],
+    static_libs: [
+        "libmodprobe",
+        "libpropertyinfoparser",
+    ],
 
     symlinks: [
         "getevent",
         "getprop",
+        "modprobe",
+        "setprop",
+        "start",
+        "stop",
     ],
 }
 
@@ -55,47 +61,3 @@
     vendor: true,
     defaults: ["toolbox_binary_defaults"],
 }
-
-// We only want 'r' on userdebug and eng builds.
-cc_binary {
-    name: "r",
-    defaults: ["toolbox_defaults"],
-    srcs: ["r.c"],
-    vendor_available: true,
-}
-
-// We build BSD grep separately (but see http://b/111849261).
-cc_defaults {
-    name: "grep_common",
-    defaults: ["toolbox_defaults"],
-    srcs: [
-        "upstream-netbsd/usr.bin/grep/fastgrep.c",
-        "upstream-netbsd/usr.bin/grep/file.c",
-        "upstream-netbsd/usr.bin/grep/grep.c",
-        "upstream-netbsd/usr.bin/grep/queue.c",
-        "upstream-netbsd/usr.bin/grep/util.c",
-    ],
-    symlinks: [
-        "egrep",
-        "fgrep",
-    ],
-    sanitize: {
-        integer_overflow: false,
-    },
-}
-
-cc_binary {
-    name: "grep",
-    defaults: ["grep_common"],
-    recovery_available: true,
-}
-
-// Build vendor grep.
-// TODO: Add vendor_available to "grep" module and remove "grep_vendor" module
-//       when vendor_available is fully supported.
-cc_binary {
-    name: "grep_vendor",
-    stem: "grep",
-    vendor: true,
-    defaults: ["grep_common"],
-}
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
new file mode 100644
index 0000000..1b5f54e
--- /dev/null
+++ b/toolbox/modprobe.cpp
@@ -0,0 +1,201 @@
+/*
+ * 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 <ctype.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <android-base/strings.h>
+#include <modprobe/modprobe.h>
+
+enum modprobe_mode {
+    AddModulesMode,
+    RemoveModulesMode,
+    ListModulesMode,
+    ShowDependenciesMode,
+};
+
+static void print_usage(void) {
+    std::cerr << "Usage:" << std::endl;
+    std::cerr << std::endl;
+    std::cerr << "  modprobe [-alrqvsDb] [-d DIR] [MODULE]+" << std::endl;
+    std::cerr << "  modprobe [-alrqvsDb] [-d DIR] MODULE [symbol=value][...]" << std::endl;
+    std::cerr << std::endl;
+    std::cerr << "Options:" << std::endl;
+    std::cerr << "  -b: Apply blacklist to module names too" << std::endl;
+    std::cerr << "  -d: Load modules from DIR, option may be used multiple times" << std::endl;
+    std::cerr << "  -D: Print dependencies for modules only, do not load";
+    std::cerr << "  -h: Print this help" << std::endl;
+    std::cerr << "  -l: List modules matching pattern" << std::endl;
+    std::cerr << "  -r: Remove MODULE (multiple modules may be specified)" << std::endl;
+    std::cerr << "  -q: Quiet" << std::endl;
+    std::cerr << "  -v: Verbose" << std::endl;
+    std::cerr << std::endl;
+}
+
+#define check_mode()                                                      \
+    if (mode != AddModulesMode) {                                         \
+        std::cerr << "Error, multiple mode flags specified" << std::endl; \
+        print_usage();                                                    \
+        return EXIT_FAILURE;                                              \
+    }
+
+extern "C" int modprobe_main(int argc, char** argv) {
+    std::vector<std::string> modules;
+    std::string module_parameters;
+    std::vector<std::string> mod_dirs;
+    modprobe_mode mode = AddModulesMode;
+    bool blacklist = false;
+    bool verbose = false;
+    int rv = EXIT_SUCCESS;
+
+    int opt;
+    while ((opt = getopt(argc, argv, "abd:Dhlqrv")) != -1) {
+        switch (opt) {
+            case 'a':
+                // toybox modprobe supported -a to load multiple modules, this
+                // is supported here by default, ignore flag
+                check_mode();
+                break;
+            case 'b':
+                blacklist = true;
+                break;
+            case 'd':
+                mod_dirs.emplace_back(optarg);
+                break;
+            case 'D':
+                check_mode();
+                mode = ShowDependenciesMode;
+                break;
+            case 'h':
+                print_usage();
+                return EXIT_SUCCESS;
+            case 'l':
+                check_mode();
+                mode = ListModulesMode;
+                break;
+            case 'q':
+                verbose = false;
+                break;
+            case 'r':
+                check_mode();
+                mode = RemoveModulesMode;
+                break;
+            case 'v':
+                verbose = true;
+                break;
+            default:
+                std::cerr << "Unrecognized option: " << opt << std::endl;
+                return EXIT_FAILURE;
+        }
+    }
+
+    int parameter_count = 0;
+    for (opt = optind; opt < argc; opt++) {
+        if (!strchr(argv[opt], '=')) {
+            modules.emplace_back(argv[opt]);
+        } else {
+            parameter_count++;
+            if (module_parameters.empty()) {
+                module_parameters = argv[opt];
+            } else {
+                module_parameters = module_parameters + " " + argv[opt];
+            }
+        }
+    }
+
+    if (verbose) {
+        std::cout << "mode is " << mode << std::endl;
+        std::cout << "verbose is " << verbose << std::endl;
+        std::cout << "mod_dirs is: " << android::base::Join(mod_dirs, "") << std::endl;
+        std::cout << "modules is: " << android::base::Join(modules, "") << std::endl;
+        std::cout << "module parameters is: " << android::base::Join(module_parameters, "")
+                  << std::endl;
+    }
+
+    if (modules.empty()) {
+        if (mode == ListModulesMode) {
+            // emulate toybox modprobe list with no pattern (list all)
+            modules.emplace_back("*");
+        } else {
+            std::cerr << "No modules given." << std::endl;
+            print_usage();
+            return EXIT_FAILURE;
+        }
+    }
+    if (mod_dirs.empty()) {
+        std::cerr << "No module configuration directories given." << std::endl;
+        print_usage();
+        return EXIT_FAILURE;
+    }
+    if (parameter_count && modules.size() > 1) {
+        std::cerr << "Only one module may be loaded when specifying module parameters."
+                  << std::endl;
+        print_usage();
+        return EXIT_FAILURE;
+    }
+
+    Modprobe m(mod_dirs);
+    m.EnableVerbose(verbose);
+    if (blacklist) {
+        m.EnableBlacklist(true);
+    }
+
+    for (const auto& module : modules) {
+        switch (mode) {
+            case AddModulesMode:
+                if (!m.LoadWithAliases(module, true, module_parameters)) {
+                    std::cerr << "Failed to load module " << module;
+                    rv = EXIT_FAILURE;
+                }
+                break;
+            case RemoveModulesMode:
+                if (!m.Remove(module)) {
+                    std::cerr << "Failed to remove module " << module;
+                    rv = EXIT_FAILURE;
+                }
+                break;
+            case ListModulesMode: {
+                std::vector<std::string> list = m.ListModules(module);
+                std::cout << android::base::Join(list, "\n") << std::endl;
+                break;
+            }
+            case ShowDependenciesMode: {
+                std::vector<std::string> pre_deps;
+                std::vector<std::string> deps;
+                std::vector<std::string> post_deps;
+                if (!m.GetAllDependencies(module, &pre_deps, &deps, &post_deps)) {
+                    rv = EXIT_FAILURE;
+                    break;
+                }
+                std::cout << "Dependencies for " << module << ":" << std::endl;
+                std::cout << "Soft pre-dependencies:" << std::endl;
+                std::cout << android::base::Join(pre_deps, "\n") << std::endl;
+                std::cout << "Hard dependencies:" << std::endl;
+                std::cout << android::base::Join(deps, "\n") << std::endl;
+                std::cout << "Soft post-dependencies:" << std::endl;
+                std::cout << android::base::Join(post_deps, "\n") << std::endl;
+                break;
+            }
+            default:
+                std::cerr << "Bad mode";
+                rv = EXIT_FAILURE;
+        }
+    }
+
+    return rv;
+}
diff --git a/toolbox/r.c b/toolbox/r.c
deleted file mode 100644
index b96cdb2..0000000
--- a/toolbox/r.c
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#if __LP64__
-#define strtoptr strtoull
-#else
-#define strtoptr strtoul
-#endif
-
-static int usage()
-{
-    fprintf(stderr,"r [-b|-s] <address> [<value>]\n");
-    return -1;
-}
-
-int main(int argc, char *argv[])
-{
-    if(argc < 2) return usage();
-
-    int width = 4;
-    if(!strcmp(argv[1], "-b")) {
-        width = 1;
-        argc--;
-        argv++;
-    } else if(!strcmp(argv[1], "-s")) {
-        width = 2;
-        argc--;
-        argv++;
-    }
-
-    if(argc < 2) return usage();
-    uintptr_t addr = strtoptr(argv[1], 0, 16);
-
-    uintptr_t endaddr = 0;
-    char* end = strchr(argv[1], '-');
-    if (end)
-        endaddr = strtoptr(end + 1, 0, 16);
-
-    if (!endaddr)
-        endaddr = addr + width - 1;
-
-    if (endaddr <= addr) {
-        fprintf(stderr, "end address <= start address\n");
-        return -1;
-    }
-
-    bool set = false;
-    uint32_t value = 0;
-    if(argc > 2) {
-        set = true;
-        value = strtoul(argv[2], 0, 16);
-    }
-
-    int fd = open("/dev/mem", O_RDWR | O_SYNC);
-    if(fd < 0) {
-        fprintf(stderr,"cannot open /dev/mem\n");
-        return -1;
-    }
-
-    off64_t mmap_start = addr & ~(PAGE_SIZE - 1);
-    size_t mmap_size = endaddr - mmap_start + 1;
-    mmap_size = (mmap_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
-
-    void* page = mmap64(0, mmap_size, PROT_READ | PROT_WRITE,
-                        MAP_SHARED, fd, mmap_start);
-
-    if(page == MAP_FAILED){
-        fprintf(stderr,"cannot mmap region\n");
-        return -1;
-    }
-
-    while (addr <= endaddr) {
-        switch(width){
-        case 4: {
-            uint32_t* x = (uint32_t*) (((uintptr_t) page) + (addr & 4095));
-            if(set) *x = value;
-            fprintf(stderr,"%08"PRIxPTR": %08x\n", addr, *x);
-            break;
-        }
-        case 2: {
-            uint16_t* x = (uint16_t*) (((uintptr_t) page) + (addr & 4095));
-            if(set) *x = value;
-            fprintf(stderr,"%08"PRIxPTR": %04x\n", addr, *x);
-            break;
-        }
-        case 1: {
-            uint8_t* x = (uint8_t*) (((uintptr_t) page) + (addr & 4095));
-            if(set) *x = value;
-            fprintf(stderr,"%08"PRIxPTR": %02x\n", addr, *x);
-            break;
-        }
-        }
-        addr += width;
-    }
-    return 0;
-}
diff --git a/toolbox/setprop.cpp b/toolbox/setprop.cpp
new file mode 100644
index 0000000..acf8c3e
--- /dev/null
+++ b/toolbox/setprop.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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 <ctype.h>
+#include <stdlib.h>
+#include <sys/system_properties.h>
+
+#include <iostream>
+
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+
+using android::base::SetProperty;
+using android::base::StartsWith;
+
+extern "C" int setprop_main(int argc, char** argv) {
+    if (argc != 3) {
+        std::cout << "usage: setprop NAME VALUE\n"
+                     "\n"
+                     "Sets an Android system property."
+                  << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    auto name = std::string{argv[1]};
+    auto value = std::string{argv[2]};
+
+    // SetProperty() doesn't tell us why it failed, and actually can't recognize most failures, so
+    // we duplicate some of init's checks here to help the user.
+
+    if (name.front() == '.' || name.back() == '.') {
+        std::cerr << "Property names must not start or end with a '.'" << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    if (name.find("..") != std::string::npos) {
+        std::cerr << "'..' is not allowed in a property name" << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    for (const auto& c : name) {
+        if (!isalnum(c) && !strchr(":@_.-", c)) {
+            std::cerr << "Invalid character '" << c << "' in name '" << name << "'" << std::endl;
+            return EXIT_FAILURE;
+        }
+    }
+
+    if (value.size() >= PROP_VALUE_MAX && !StartsWith(value, "ro.")) {
+        std::cerr << "Value '" << value << "' is too long, " << value.size()
+                  << " bytes vs a max of " << PROP_VALUE_MAX << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
+        std::cerr << "Value '" << value << "' is not a UTF8 encoded string" << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    if (!SetProperty(name, value)) {
+        std::cerr << "Failed to set property '" << name << "' to '" << value
+                  << "'.\nSee dmesg for error reason." << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/toolbox/start.cpp b/toolbox/start.cpp
new file mode 100644
index 0000000..b87ed15
--- /dev/null
+++ b/toolbox/start.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <android-base/properties.h>
+
+using android::base::GetProperty;
+using android::base::SetProperty;
+using namespace std::literals;
+
+static void ControlService(bool start, const std::string& service) {
+    if (!android::base::SetProperty(start ? "ctl.start" : "ctl.stop", service)) {
+        std::cerr << "Unable to " << (start ? "start" : "stop") << " service '" << service
+                  << "'\nSee dmesg for error reason." << std::endl;
+        exit(EXIT_FAILURE);
+    }
+}
+
+static void ControlDefaultServices(bool start) {
+    std::vector<std::string> services = {"netd", "surfaceflinger", "zygote"};
+
+    // Only start zygote_secondary if not single arch.
+    std::string zygote_configuration = GetProperty("ro.zygote", "");
+    if (zygote_configuration != "zygote32" && zygote_configuration != "zygote64") {
+        services.emplace_back("zygote_secondary");
+    }
+
+    if (start) {
+        for (const auto& service : services) {
+            ControlService(true, service);
+        }
+    } else {
+        for (auto it = services.crbegin(); it != services.crend(); ++it) {
+            ControlService(false, *it);
+        }
+    }
+}
+
+static int StartStop(int argc, char** argv, bool start) {
+    if (getuid()) {
+        std::cerr << "Must be root" << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    if (argc == 1) {
+        ControlDefaultServices(start);
+    }
+
+    if (argc == 2 && argv[1] == "--help"s) {
+        std::cout << "usage: " << (start ? "start" : "stop")
+                  << " [SERVICE...]\n"
+                     "\n"
+                  << (start ? "Starts" : "Stops")
+                  << " the given system service, or netd/surfaceflinger/zygotes." << std::endl;
+        return EXIT_SUCCESS;
+    }
+
+    for (int i = 1; i < argc; ++i) {
+        ControlService(start, argv[i]);
+    }
+    return EXIT_SUCCESS;
+}
+
+extern "C" int start_main(int argc, char** argv) {
+    return StartStop(argc, argv, true);
+}
+
+extern "C" int stop_main(int argc, char** argv) {
+    return StartStop(argc, argv, false);
+}
\ No newline at end of file
diff --git a/toolbox/tools.h b/toolbox/tools.h
index abeb3ef..bb57e67 100644
--- a/toolbox/tools.h
+++ b/toolbox/tools.h
@@ -1,3 +1,7 @@
 TOOL(getevent)
 TOOL(getprop)
+TOOL(modprobe)
+TOOL(setprop)
+TOOL(start)
+TOOL(stop)
 TOOL(toolbox)
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c b/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c
deleted file mode 100644
index 2fcd864..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/fastgrep.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*	$OpenBSD: util.c,v 1.36 2007/10/02 17:59:18 otto Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/fastgrep.c 211496 2010-08-19 09:28:59Z des $ */
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * XXX: This file is a speed up for grep to cover the defects of the
- * regex library.  These optimizations should practically be implemented
- * there keeping this code clean.  This is a future TODO, but for the
- * meantime, we need to use this workaround.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: fastgrep.c,v 1.5 2011/04/18 03:27:40 joerg Exp $");
-
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-static inline int	grep_cmp(const unsigned char *, const unsigned char *, size_t);
-static inline void	grep_revstr(unsigned char *, int);
-
-void
-fgrepcomp(fastgrep_t *fg, const char *pat)
-{
-	unsigned int i;
-
-	/* Initialize. */
-	fg->len = strlen(pat);
-	fg->bol = false;
-	fg->eol = false;
-	fg->reversed = false;
-
-	fg->pattern = (unsigned char *)grep_strdup(pat);
-
-	/* Preprocess pattern. */
-	for (i = 0; i <= UCHAR_MAX; i++)
-		fg->qsBc[i] = fg->len;
-	for (i = 1; i < fg->len; i++)
-		fg->qsBc[fg->pattern[i]] = fg->len - i;
-}
-
-/*
- * Returns: -1 on failure, 0 on success
- */
-int
-fastcomp(fastgrep_t *fg, const char *pat)
-{
-	unsigned int i;
-	int firstHalfDot = -1;
-	int firstLastHalfDot = -1;
-	int hasDot = 0;
-	int lastHalfDot = 0;
-	int shiftPatternLen;
-
-	/* Initialize. */
-	fg->len = strlen(pat);
-	fg->bol = false;
-	fg->eol = false;
-	fg->reversed = false;
-	fg->word = wflag;
-
-	/* Remove end-of-line character ('$'). */
-	if (fg->len > 0 && pat[fg->len - 1] == '$') {
-		fg->eol = true;
-		fg->len--;
-	}
-
-	/* Remove beginning-of-line character ('^'). */
-	if (pat[0] == '^') {
-		fg->bol = true;
-		fg->len--;
-		pat++;
-	}
-
-	if (fg->len >= 14 &&
-	    memcmp(pat, "[[:<:]]", 7) == 0 &&
-	    memcmp(pat + fg->len - 7, "[[:>:]]", 7) == 0) {
-		fg->len -= 14;
-		pat += 7;
-		/* Word boundary is handled separately in util.c */
-		fg->word = true;
-	}
-
-	/*
-	 * pat has been adjusted earlier to not include '^', '$' or
-	 * the word match character classes at the beginning and ending
-	 * of the string respectively.
-	 */
-	fg->pattern = grep_malloc(fg->len + 1);
-	memcpy(fg->pattern, pat, fg->len);
-	fg->pattern[fg->len] = '\0';
-
-	/* Look for ways to cheat...er...avoid the full regex engine. */
-	for (i = 0; i < fg->len; i++) {
-		/* Can still cheat? */
-		if (fg->pattern[i] == '.') {
-			hasDot = i;
-			if (i < fg->len / 2) {
-				if (firstHalfDot < 0)
-					/* Closest dot to the beginning */
-					firstHalfDot = i;
-			} else {
-				/* Closest dot to the end of the pattern. */
-				lastHalfDot = i;
-				if (firstLastHalfDot < 0)
-					firstLastHalfDot = i;
-			}
-		} else {
-			/* Free memory and let others know this is empty. */
-			free(fg->pattern);
-			fg->pattern = NULL;
-			return (-1);
-		}
-	}
-
-	/*
-	 * Determine if a reverse search would be faster based on the placement
-	 * of the dots.
-	 */
-	if ((!(lflag || cflag)) && ((!(fg->bol || fg->eol)) &&
-	    ((lastHalfDot) && ((firstHalfDot < 0) ||
-	    ((fg->len - (lastHalfDot + 1)) < (size_t)firstHalfDot)))) &&
-	    !oflag && !color) {
-		fg->reversed = true;
-		hasDot = fg->len - (firstHalfDot < 0 ?
-		    firstLastHalfDot : firstHalfDot) - 1;
-		grep_revstr(fg->pattern, fg->len);
-	}
-
-	/*
-	 * Normal Quick Search would require a shift based on the position the
-	 * next character after the comparison is within the pattern.  With
-	 * wildcards, the position of the last dot effects the maximum shift
-	 * distance.
-	 * The closer to the end the wild card is the slower the search.  A
-	 * reverse version of this algorithm would be useful for wildcards near
-	 * the end of the string.
-	 *
-	 * Examples:
-	 * Pattern	Max shift
-	 * -------	---------
-	 * this		5
-	 * .his		4
-	 * t.is		3
-	 * th.s		2
-	 * thi.		1
-	 */
-
-	/* Adjust the shift based on location of the last dot ('.'). */
-	shiftPatternLen = fg->len - hasDot;
-
-	/* Preprocess pattern. */
-	for (i = 0; i <= (signed)UCHAR_MAX; i++)
-		fg->qsBc[i] = shiftPatternLen;
-	for (i = hasDot + 1; i < fg->len; i++) {
-		fg->qsBc[fg->pattern[i]] = fg->len - i;
-	}
-
-	/*
-	 * Put pattern back to normal after pre-processing to allow for easy
-	 * comparisons later.
-	 */
-	if (fg->reversed)
-		grep_revstr(fg->pattern, fg->len);
-
-	return (0);
-}
-
-int
-grep_search(fastgrep_t *fg, const unsigned char *data, size_t len, regmatch_t *pmatch)
-{
-	unsigned int j;
-	int ret = REG_NOMATCH;
-
-	if (pmatch->rm_so == (ssize_t)len)
-		return (ret);
-
-	if (fg->bol && pmatch->rm_so != 0) {
-		pmatch->rm_so = len;
-		pmatch->rm_eo = len;
-		return (ret);
-	}
-
-	/* No point in going farther if we do not have enough data. */
-	if (len < fg->len)
-		return (ret);
-
-	/* Only try once at the beginning or ending of the line. */
-	if (fg->bol || fg->eol) {
-		/* Simple text comparison. */
-		/* Verify data is >= pattern length before searching on it. */
-		if (len >= fg->len) {
-			/* Determine where in data to start search at. */
-			j = fg->eol ? len - fg->len : 0;
-			if (!((fg->bol && fg->eol) && (len != fg->len)))
-				if (grep_cmp(fg->pattern, data + j,
-				    fg->len) == -1) {
-					pmatch->rm_so = j;
-					pmatch->rm_eo = j + fg->len;
-						ret = 0;
-				}
-		}
-	} else if (fg->reversed) {
-		/* Quick Search algorithm. */
-		j = len;
-		do {
-			if (grep_cmp(fg->pattern, data + j - fg->len,
-				fg->len) == -1) {
-				pmatch->rm_so = j - fg->len;
-				pmatch->rm_eo = j;
-				ret = 0;
-				break;
-			}
-			/* Shift if within bounds, otherwise, we are done. */
-			if (j == fg->len)
-				break;
-			j -= fg->qsBc[data[j - fg->len - 1]];
-		} while (j >= fg->len);
-	} else {
-		/* Quick Search algorithm. */
-		j = pmatch->rm_so;
-		do {
-			if (grep_cmp(fg->pattern, data + j, fg->len) == -1) {
-				pmatch->rm_so = j;
-				pmatch->rm_eo = j + fg->len;
-				ret = 0;
-				break;
-			}
-
-			/* Shift if within bounds, otherwise, we are done. */
-			if (j + fg->len == len)
-				break;
-			else
-				j += fg->qsBc[data[j + fg->len]];
-		} while (j <= (len - fg->len));
-	}
-
-	return (ret);
-}
-
-/*
- * Returns:	i >= 0 on failure (position that it failed)
- *		-1 on success
- */
-static inline int
-grep_cmp(const unsigned char *pat, const unsigned char *data, size_t len)
-{
-	size_t size;
-	wchar_t *wdata, *wpat;
-	unsigned int i;
-
-	if (iflag) {
-		if ((size = mbstowcs(NULL, (const char *)data, 0)) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		wdata = grep_malloc(size * sizeof(wint_t));
-
-		if (mbstowcs(wdata, (const char *)data, size) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		if ((size = mbstowcs(NULL, (const char *)pat, 0)) ==
-		    ((size_t) - 1))
-			return (-1);
-
-		wpat = grep_malloc(size * sizeof(wint_t));
-
-		if (mbstowcs(wpat, (const char *)pat, size) == ((size_t) - 1))
-			return (-1);
-		for (i = 0; i < len; i++) {
-			if ((towlower(wpat[i]) == towlower(wdata[i])) ||
-			    ((grepbehave != GREP_FIXED) && wpat[i] == L'.'))
-				continue;
-			free(wpat);
-			free(wdata);
-				return (i);
-		}
-	} else {
-		for (i = 0; i < len; i++) {
-			if ((pat[i] == data[i]) || ((grepbehave != GREP_FIXED) &&
-			    pat[i] == '.'))
-				continue;
-			return (i);
-		}
-	}
-	return (-1);
-}
-
-static inline void
-grep_revstr(unsigned char *str, int len)
-{
-	int i;
-	char c;
-
-	for (i = 0; i < len / 2; i++) {
-		c = str[i];
-		str[i] = str[len - i - 1];
-		str[len - i - 1] = c;
-	}
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/file.c b/toolbox/upstream-netbsd/usr.bin/grep/file.c
deleted file mode 100644
index 428bf58..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/file.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*	$NetBSD: file.c,v 1.10 2018/08/12 09:03:21 christos Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/file.c 211496 2010-08-19 09:28:59Z des $	*/
-/*	$OpenBSD: file.c,v 1.11 2010/07/02 20:48:48 nicm Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
- * Copyright (C) 2010 Dimitry Andric <dimitry@andric.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: file.c,v 1.10 2018/08/12 09:03:21 christos Exp $");
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-#define	MAXBUFSIZ	(32 * 1024)
-#define	LNBUFBUMP	80
-
-#ifndef WITHOUT_GZIP
-static gzFile gzbufdesc;
-#endif
-#ifndef WITHOUT_BZ2
-static BZFILE* bzbufdesc;
-#endif
-
-static unsigned char buffer[MAXBUFSIZ + 1];
-static unsigned char *bufpos;
-static size_t bufrem;
-
-static unsigned char *lnbuf;
-static size_t lnbuflen;
-
-static inline int
-grep_refill(struct file *f)
-{
-	ssize_t nr = -1;
-	int bzerr;
-
-	bufpos = buffer;
-	bufrem = 0;
-
-#ifndef WITHOUT_GZIP
-	if (filebehave == FILE_GZIP) {
-		nr = gzread(gzbufdesc, buffer, MAXBUFSIZ);
-		if (nr == -1)
-			return -1;
-	}
-#endif
-#ifndef WITHOUT_BZ2
-	if (filebehave == FILE_BZIP && bzbufdesc != NULL) {
-		nr = BZ2_bzRead(&bzerr, bzbufdesc, buffer, MAXBUFSIZ);
-		switch (bzerr) {
-		case BZ_OK:
-		case BZ_STREAM_END:
-			/* No problem, nr will be okay */
-			break;
-		case BZ_DATA_ERROR_MAGIC:
-			/*
-			 * As opposed to gzread(), which simply returns the
-			 * plain file data, if it is not in the correct
-			 * compressed format, BZ2_bzRead() instead aborts.
-			 *
-			 * So, just restart at the beginning of the file again,
-			 * and use plain reads from now on.
-			 */
-			BZ2_bzReadClose(&bzerr, bzbufdesc);
-			bzbufdesc = NULL;
-			if (lseek(f->fd, 0, SEEK_SET) == -1)
-				return (-1);
-			nr = read(f->fd, buffer, MAXBUFSIZ);
-			break;
-		default:
-			/* Make sure we exit with an error */
-			nr = -1;
-		}
-		if (nr == -1)
-			return -1;
-	}
-#endif
-	if (nr == -1) {
-		nr = read(f->fd, buffer, MAXBUFSIZ);
-	}
-
-	if (nr < 0)
-		return (-1);
-
-	bufrem = nr;
-	return (0);
-}
-
-static inline void
-grep_lnbufgrow(size_t newlen)
-{
-
-	if (lnbuflen < newlen) {
-		lnbuf = grep_realloc(lnbuf, newlen);
-		lnbuflen = newlen;
-	}
-}
-
-char *
-grep_fgetln(struct file *f, size_t *lenp)
-{
-	unsigned char *p;
-	char *ret;
-	size_t len;
-	size_t off;
-	ptrdiff_t diff;
-
-	/* Fill the buffer, if necessary */
-	if (bufrem == 0 && grep_refill(f) != 0)
-		goto error;
-
-	if (bufrem == 0) {
-		/* Return zero length to indicate EOF */
-		*lenp = 0;
-		return ((char *)bufpos);
-	}
-
-	/* Look for a newline in the remaining part of the buffer */
-	if ((p = memchr(bufpos, line_sep, bufrem)) != NULL) {
-		++p; /* advance over newline */
-		len = p - bufpos;
-		grep_lnbufgrow(len + 1);
-		memcpy(lnbuf, bufpos, len);
-		lnbuf[len] = '\0';
-		*lenp = len;
-		bufrem -= len;
-		bufpos = p;
-		return ((char *)lnbuf);
-	}
-
-	/* We have to copy the current buffered data to the line buffer */
-	for (len = bufrem, off = 0; ; len += bufrem) {
-		/* Make sure there is room for more data */
-		grep_lnbufgrow(len + LNBUFBUMP);
-		memcpy(lnbuf + off, bufpos, len - off);
-		lnbuf[len] = '\0';
-		off = len;
-		if (grep_refill(f) != 0)
-			goto error;
-		if (bufrem == 0)
-			/* EOF: return partial line */
-			break;
-		if ((p = memchr(bufpos, line_sep, bufrem)) == NULL)
-			continue;
-		/* got it: finish up the line (like code above) */
-		++p;
-		diff = p - bufpos;
-		len += diff;
-		grep_lnbufgrow(len + 1);
-		memcpy(lnbuf + off, bufpos, diff);
-		lnbuf[off + diff] = '\0';
-		bufrem -= diff;
-		bufpos = p;
-		break;
-	}
-	*lenp = len;
-	return ((char *)lnbuf);
-
-error:
-	*lenp = 0;
-	return (NULL);
-}
-
-static inline struct file *
-grep_file_init(struct file *f)
-{
-
-#ifndef WITHOUT_GZIP
-	if (filebehave == FILE_GZIP &&
-	    (gzbufdesc = gzdopen(f->fd, "r")) == NULL)
-		goto error;
-#endif
-
-#ifndef WITHOUT_BZ2
-	if (filebehave == FILE_BZIP &&
-	    (bzbufdesc = BZ2_bzdopen(f->fd, "r")) == NULL)
-		goto error;
-#endif
-
-	/* Fill read buffer, also catches errors early */
-	if (grep_refill(f) != 0)
-		goto error;
-
-	/* Check for binary stuff, if necessary */
-	if (!nulldataflag && binbehave != BINFILE_TEXT &&
-	    memchr(bufpos, '\0', bufrem) != NULL)
-		f->binary = true;
-
-	return (f);
-error:
-	close(f->fd);
-	free(f);
-	return (NULL);
-}
-
-/*
- * Opens a file for processing.
- */
-struct file *
-grep_open(const char *path)
-{
-	struct file *f;
-
-	f = grep_malloc(sizeof *f);
-	memset(f, 0, sizeof *f);
-	if (path == NULL) {
-		/* Processing stdin implies --line-buffered. */
-		lbflag = true;
-		f->fd = STDIN_FILENO;
-	} else if ((f->fd = open(path, O_RDONLY)) == -1) {
-		free(f);
-		return (NULL);
-	}
-
-	return (grep_file_init(f));
-}
-
-/*
- * Closes a file.
- */
-void
-grep_close(struct file *f)
-{
-
-	close(f->fd);
-
-	/* Reset read buffer and line buffer */
-	bufpos = buffer;
-	bufrem = 0;
-
-	free(lnbuf);
-	lnbuf = NULL;
-	lnbuflen = 0;
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.c b/toolbox/upstream-netbsd/usr.bin/grep/grep.c
deleted file mode 100644
index bad2a73..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*	$NetBSD: grep.c,v 1.15 2018/08/12 09:03:21 christos Exp $	*/
-/* 	$FreeBSD: head/usr.bin/grep/grep.c 211519 2010-08-19 22:55:17Z delphij $	*/
-/*	$OpenBSD: grep.c,v 1.42 2010/07/02 22:18:03 tedu Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: grep.c,v 1.15 2018/08/12 09:03:21 christos Exp $");
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <libgen.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "grep.h"
-
-#ifndef WITHOUT_NLS
-#include <nl_types.h>
-nl_catd	 catalog;
-#endif
-
-/*
- * Default messags to use when NLS is disabled or no catalogue
- * is found.
- */
-const char	*errstr[] = {
-	"",
-/* 1*/	"(standard input)",
-/* 2*/	"cannot read bzip2 compressed file",
-/* 3*/	"unknown %s option",
-/* 4*/	"usage: %s [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZz] [-A num] [-B num] [-C[num]]\n",
-/* 5*/	"\t[-e pattern] [-f file] [--binary-files=value] [--color=when]\n",
-/* 6*/	"\t[--context[=num]] [--directories=action] [--label] [--line-buffered]\n",
-/* 7*/	"\t[pattern] [file ...]\n",
-/* 8*/	"Binary file %s matches\n",
-/* 9*/	"%s (BSD grep) %s\n",
-};
-
-/* Flags passed to regcomp() and regexec() */
-int		 cflags = 0;
-int		 eflags = REG_STARTEND;
-
-/* Searching patterns */
-unsigned int	 patterns, pattern_sz;
-char		**pattern;
-regex_t		*r_pattern;
-fastgrep_t	*fg_pattern;
-
-/* Filename exclusion/inclusion patterns */
-unsigned int	 fpatterns, fpattern_sz;
-unsigned int	 dpatterns, dpattern_sz;
-struct epat	*dpattern, *fpattern;
-
-/* For regex errors  */
-char	 re_error[RE_ERROR_BUF + 1];
-
-/* Command-line flags */
-unsigned long long Aflag;	/* -A x: print x lines trailing each match */
-unsigned long long Bflag;	/* -B x: print x lines leading each match */
-bool	 Hflag;		/* -H: always print file name */
-bool	 Lflag;		/* -L: only show names of files with no matches */
-bool	 bflag;		/* -b: show block numbers for each match */
-bool	 cflag;		/* -c: only show a count of matching lines */
-bool	 hflag;		/* -h: don't print filename headers */
-bool	 iflag;		/* -i: ignore case */
-bool	 lflag;		/* -l: only show names of files with matches */
-bool	 mflag;		/* -m x: stop reading the files after x matches */
-unsigned long long mcount;	/* count for -m */
-bool	 nflag;		/* -n: show line numbers in front of matching lines */
-bool	 oflag;		/* -o: print only matching part */
-bool	 qflag;		/* -q: quiet mode (don't output anything) */
-bool	 sflag;		/* -s: silent mode (ignore errors) */
-bool	 vflag;		/* -v: only show non-matching lines */
-bool	 wflag;		/* -w: pattern must start and end on word boundaries */
-bool	 xflag;		/* -x: pattern must match entire line */
-bool	 lbflag;	/* --line-buffered */
-bool	 nullflag;	/* --null */
-bool	 nulldataflag;	/* --null-data */
-unsigned char line_sep = '\n';	/* 0 for --null-data */
-char	*label;		/* --label */
-const char *color;	/* --color */
-int	 grepbehave = GREP_BASIC;	/* -EFGP: type of the regex */
-int	 binbehave = BINFILE_BIN;	/* -aIU: handling of binary files */
-int	 filebehave = FILE_STDIO;	/* -JZ: normal, gzip or bzip2 file */
-int	 devbehave = DEV_READ;		/* -D: handling of devices */
-int	 dirbehave = DIR_READ;		/* -dRr: handling of directories */
-int	 linkbehave = LINK_READ;	/* -OpS: handling of symlinks */
-
-bool	 dexclude, dinclude;	/* --exclude-dir and --include-dir */
-bool	 fexclude, finclude;	/* --exclude and --include */
-
-enum {
-	BIN_OPT = CHAR_MAX + 1,
-	COLOR_OPT,
-	DECOMPRESS_OPT,
-	HELP_OPT,
-	MMAP_OPT,
-	LINEBUF_OPT,
-	LABEL_OPT,
-	R_EXCLUDE_OPT,
-	R_INCLUDE_OPT,
-	R_DEXCLUDE_OPT,
-	R_DINCLUDE_OPT
-};
-
-static inline const char	*init_color(const char *);
-
-/* Housekeeping */
-int	 tail;		/* lines left to print */
-bool	 notfound;	/* file not found */
-
-extern char	*__progname;
-
-/*
- * Prints usage information and returns 2.
- */
-__dead static void
-usage(void)
-{
-	fprintf(stderr, getstr(4), __progname);
-	fprintf(stderr, "%s", getstr(5));
-	fprintf(stderr, "%s", getstr(6));
-	fprintf(stderr, "%s", getstr(7));
-	exit(2);
-}
-
-static const char optstr[] =
-    "0123456789A:B:C:D:EFGHIJLOPSRUVZabcd:e:f:hilm:nopqrsuvwxyz";
-
-struct option long_options[] =
-{
-	{"binary-files",	required_argument,	NULL, BIN_OPT},
-#ifndef WITHOUT_GZIP
-	{"decompress",          no_argument,            NULL, DECOMPRESS_OPT},
-#endif
-	{"help",		no_argument,		NULL, HELP_OPT},
-	{"mmap",		no_argument,		NULL, MMAP_OPT},
-	{"line-buffered",	no_argument,		NULL, LINEBUF_OPT},
-	{"label",		required_argument,	NULL, LABEL_OPT},
-	{"color",		optional_argument,	NULL, COLOR_OPT},
-	{"colour",		optional_argument,	NULL, COLOR_OPT},
-	{"exclude",		required_argument,	NULL, R_EXCLUDE_OPT},
-	{"include",		required_argument,	NULL, R_INCLUDE_OPT},
-	{"exclude-dir",		required_argument,	NULL, R_DEXCLUDE_OPT},
-	{"include-dir",		required_argument,	NULL, R_DINCLUDE_OPT},
-	{"after-context",	required_argument,	NULL, 'A'},
-	{"text",		no_argument,		NULL, 'a'},
-	{"before-context",	required_argument,	NULL, 'B'},
-	{"byte-offset",		no_argument,		NULL, 'b'},
-	{"context",		optional_argument,	NULL, 'C'},
-	{"count",		no_argument,		NULL, 'c'},
-	{"devices",		required_argument,	NULL, 'D'},
-        {"directories",		required_argument,	NULL, 'd'},
-	{"extended-regexp",	no_argument,		NULL, 'E'},
-	{"regexp",		required_argument,	NULL, 'e'},
-	{"fixed-strings",	no_argument,		NULL, 'F'},
-	{"file",		required_argument,	NULL, 'f'},
-	{"basic-regexp",	no_argument,		NULL, 'G'},
-	{"no-filename",		no_argument,		NULL, 'h'},
-	{"with-filename",	no_argument,		NULL, 'H'},
-	{"ignore-case",		no_argument,		NULL, 'i'},
-#ifndef WITHOUT_BZ2
-	{"bz2decompress",	no_argument,		NULL, 'J'},
-#endif
-	{"files-with-matches",	no_argument,		NULL, 'l'},
-	{"files-without-match", no_argument,            NULL, 'L'},
-	{"max-count",		required_argument,	NULL, 'm'},
-	{"line-number",		no_argument,		NULL, 'n'},
-	{"only-matching",	no_argument,		NULL, 'o'},
-	{"quiet",		no_argument,		NULL, 'q'},
-	{"silent",		no_argument,		NULL, 'q'},
-	{"recursive",		no_argument,		NULL, 'r'},
-	{"no-messages",		no_argument,		NULL, 's'},
-	{"binary",		no_argument,		NULL, 'U'},
-	{"unix-byte-offsets",	no_argument,		NULL, 'u'},
-	{"invert-match",	no_argument,		NULL, 'v'},
-	{"version",		no_argument,		NULL, 'V'},
-	{"word-regexp",		no_argument,		NULL, 'w'},
-	{"line-regexp",		no_argument,		NULL, 'x'},
-	{"null",		no_argument,		NULL, 'Z'},
-	{"null-data",		no_argument,		NULL, 'z'},
-	{NULL,			no_argument,		NULL, 0}
-};
-
-/*
- * Adds a searching pattern to the internal array.
- */
-static void
-add_pattern(char *pat, size_t len)
-{
-
-	/* TODO: Check for empty patterns and shortcut */
-
-	/* Increase size if necessary */
-	if (patterns == pattern_sz) {
-		pattern_sz *= 2;
-		pattern = grep_realloc(pattern, ++pattern_sz *
-		    sizeof(*pattern));
-	}
-	if (len > 0 && pat[len - 1] == '\n')
-		--len;
-	/* pat may not be NUL-terminated */
-	pattern[patterns] = grep_malloc(len + 1);
-	memcpy(pattern[patterns], pat, len);
-	pattern[patterns][len] = '\0';
-	++patterns;
-}
-
-/*
- * Adds a file include/exclude pattern to the internal array.
- */
-static void
-add_fpattern(const char *pat, int mode)
-{
-
-	/* Increase size if necessary */
-	if (fpatterns == fpattern_sz) {
-		fpattern_sz *= 2;
-		fpattern = grep_realloc(fpattern, ++fpattern_sz *
-		    sizeof(struct epat));
-	}
-	fpattern[fpatterns].pat = grep_strdup(pat);
-	fpattern[fpatterns].mode = mode;
-	++fpatterns;
-}
-
-/*
- * Adds a directory include/exclude pattern to the internal array.
- */
-static void
-add_dpattern(const char *pat, int mode)
-{
-
-	/* Increase size if necessary */
-	if (dpatterns == dpattern_sz) {
-		dpattern_sz *= 2;
-		dpattern = grep_realloc(dpattern, ++dpattern_sz *
-		    sizeof(struct epat));
-	}
-	dpattern[dpatterns].pat = grep_strdup(pat);
-	dpattern[dpatterns].mode = mode;
-	++dpatterns;
-}
-
-/*
- * Reads searching patterns from a file and adds them with add_pattern().
- */
-static void
-read_patterns(const char *fn)
-{
-	FILE *f;
-	char *line;
-	size_t len;
-	ssize_t rlen;
-
-	if ((f = fopen(fn, "r")) == NULL)
-		err(2, "%s", fn);
-	line = NULL;
-	len = 0;
-	while ((rlen = getline(&line, &len, f)) != -1)
-		add_pattern(line, *line == '\n' ? 0 : (size_t)rlen);
-	free(line);
-	if (ferror(f))
-		err(2, "%s", fn);
-	fclose(f);
-}
-
-static inline const char *
-init_color(const char *d)
-{
-	char *c;
-
-	c = getenv("GREP_COLOR");
-	return (c != NULL ? c : d);
-}
-
-int
-main(int argc, char *argv[])
-{
-	char **aargv, **eargv, *eopts;
-	char *ep;
-	unsigned long long l;
-	unsigned int aargc, eargc, i, j;
-	int c, lastc, needpattern, newarg, prevoptind;
-
-	setlocale(LC_ALL, "");
-
-#ifndef WITHOUT_NLS
-	catalog = catopen("grep", NL_CAT_LOCALE);
-#endif
-
-	/* Check what is the program name of the binary.  In this
-	   way we can have all the funcionalities in one binary
-	   without the need of scripting and using ugly hacks. */
-	switch (__progname[0]) {
-	case 'e':
-		grepbehave = GREP_EXTENDED;
-		break;
-	case 'f':
-		grepbehave = GREP_FIXED;
-		break;
-	case 'g':
-		grepbehave = GREP_BASIC;
-		break;
-#ifndef WITHOUT_GZIP
-	case 'z':
-		filebehave = FILE_GZIP;
-		switch(__progname[1]) {
-		case 'e':
-			grepbehave = GREP_EXTENDED;
-			break;
-		case 'f':
-			grepbehave = GREP_FIXED;
-			break;
-		case 'g':
-			grepbehave = GREP_BASIC;
-			break;
-		}
-		break;
-#endif
-	}
-
-	lastc = '\0';
-	newarg = 1;
-	prevoptind = 1;
-	needpattern = 1;
-
-	eopts = getenv("GREP_OPTIONS");
-
-	/* support for extra arguments in GREP_OPTIONS */
-	eargc = 0;
-	if (eopts != NULL) {
-		char *str;
-
-		/* make an estimation of how many extra arguments we have */
-		for (j = 0; j < strlen(eopts); j++)
-			if (eopts[j] == ' ')
-				eargc++;
-
-		eargv = (char **)grep_malloc(sizeof(char *) * (eargc + 1));
-
-		eargc = 0;
-		/* parse extra arguments */
-		while ((str = strsep(&eopts, " ")) != NULL)
-			eargv[eargc++] = grep_strdup(str);
-
-		aargv = (char **)grep_calloc(eargc + argc + 1,
-		    sizeof(char *));
-
-		aargv[0] = argv[0];
-		for (i = 0; i < eargc; i++)
-			aargv[i + 1] = eargv[i];
-		for (j = 1; j < (unsigned int)argc; j++, i++)
-			aargv[i + 1] = argv[j];
-
-		aargc = eargc + argc;
-	} else {
-		aargv = argv;
-		aargc = argc;
-	}
-
-	while (((c = getopt_long(aargc, aargv, optstr, long_options, NULL)) !=
-	    -1)) {
-		switch (c) {
-		case '0': case '1': case '2': case '3': case '4':
-		case '5': case '6': case '7': case '8': case '9':
-			if (newarg || !isdigit(lastc))
-				Aflag = 0;
-			else if (Aflag > LLONG_MAX / 10) {
-				errno = ERANGE;
-				err(2, NULL);
-			}
-			Aflag = Bflag = (Aflag * 10) + (c - '0');
-			break;
-		case 'C':
-			if (optarg == NULL) {
-				Aflag = Bflag = 2;
-				break;
-			}
-			/* FALLTHROUGH */
-		case 'A':
-			/* FALLTHROUGH */
-		case 'B':
-			errno = 0;
-			l = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (l == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (l == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
-			if (c == 'A')
-				Aflag = l;
-			else if (c == 'B')
-				Bflag = l;
-			else
-				Aflag = Bflag = l;
-			break;
-		case 'a':
-			binbehave = BINFILE_TEXT;
-			break;
-		case 'b':
-			bflag = true;
-			break;
-		case 'c':
-			cflag = true;
-			break;
-		case 'D':
-			if (strcasecmp(optarg, "skip") == 0)
-				devbehave = DEV_SKIP;
-			else if (strcasecmp(optarg, "read") == 0)
-				devbehave = DEV_READ;
-			else
-				errx(2, getstr(3), "--devices");
-			break;
-		case 'd':
-			if (strcasecmp("recurse", optarg) == 0) {
-				Hflag = true;
-				dirbehave = DIR_RECURSE;
-			} else if (strcasecmp("skip", optarg) == 0)
-				dirbehave = DIR_SKIP;
-			else if (strcasecmp("read", optarg) == 0)
-				dirbehave = DIR_READ;
-			else
-				errx(2, getstr(3), "--directories");
-			break;
-		case 'E':
-			grepbehave = GREP_EXTENDED;
-			break;
-		case 'e':
-			add_pattern(optarg, strlen(optarg));
-			needpattern = 0;
-			break;
-		case 'F':
-			grepbehave = GREP_FIXED;
-			break;
-		case 'f':
-			read_patterns(optarg);
-			needpattern = 0;
-			break;
-		case 'G':
-			grepbehave = GREP_BASIC;
-			break;
-		case 'H':
-			Hflag = true;
-			break;
-		case 'h':
-			Hflag = false;
-			hflag = true;
-			break;
-		case 'I':
-			binbehave = BINFILE_SKIP;
-			break;
-		case 'i':
-		case 'y':
-			iflag =  true;
-			cflags |= REG_ICASE;
-			break;
-#ifndef WITHOUT_BZ2
-		case 'J':
-			filebehave = FILE_BZIP;
-			break;
-#endif
-		case 'L':
-			lflag = false;
-			Lflag = true;
-			break;
-		case 'l':
-			Lflag = false;
-			lflag = true;
-			break;
-		case 'm':
-			mflag = true;
-			errno = 0;
-			mcount = strtoull(optarg, &ep, 10);
-			if (((errno == ERANGE) && (mcount == ULLONG_MAX)) ||
-			    ((errno == EINVAL) && (mcount == 0)))
-				err(2, NULL);
-			else if (ep[0] != '\0') {
-				errno = EINVAL;
-				err(2, NULL);
-			}
-			break;
-		case 'n':
-			nflag = true;
-			break;
-		case 'O':
-			linkbehave = LINK_EXPLICIT;
-			break;
-		case 'o':
-			oflag = true;
-			break;
-		case 'p':
-			linkbehave = LINK_SKIP;
-			break;
-		case 'q':
-			qflag = true;
-			break;
-		case 'S':
-			linkbehave = LINK_READ;
-			break;
-		case 'R':
-		case 'r':
-			dirbehave = DIR_RECURSE;
-			Hflag = true;
-			break;
-		case 's':
-			sflag = true;
-			break;
-		case 'U':
-			binbehave = BINFILE_BIN;
-			break;
-		case 'u':
-		case MMAP_OPT:
-			/* noop, compatibility */
-			break;
-		case 'V':
-			printf(getstr(9), __progname, VERSION);
-			exit(0);
-		case 'v':
-			vflag = true;
-			break;
-		case 'w':
-			wflag = true;
-			break;
-		case 'x':
-			xflag = true;
-			break;
-		case 'Z':
-			nullflag = true;
-			break;
-		case 'z':
-			nulldataflag = true;
-			line_sep = '\0';
-			break;
-		case BIN_OPT:
-			if (strcasecmp("binary", optarg) == 0)
-				binbehave = BINFILE_BIN;
-			else if (strcasecmp("without-match", optarg) == 0)
-				binbehave = BINFILE_SKIP;
-			else if (strcasecmp("text", optarg) == 0)
-				binbehave = BINFILE_TEXT;
-			else
-				errx(2, getstr(3), "--binary-files");
-			break;
-		case COLOR_OPT:
-			color = NULL;
-			if (optarg == NULL || strcasecmp("auto", optarg) == 0 ||
-			    strcasecmp("tty", optarg) == 0 ||
-			    strcasecmp("if-tty", optarg) == 0) {
-				char *term;
-
-				term = getenv("TERM");
-				if (isatty(STDOUT_FILENO) && term != NULL &&
-				    strcasecmp(term, "dumb") != 0)
-					color = init_color("01;31");
-			} else if (strcasecmp("always", optarg) == 0 ||
-			    strcasecmp("yes", optarg) == 0 ||
-			    strcasecmp("force", optarg) == 0) {
-				color = init_color("01;31");
-			} else if (strcasecmp("never", optarg) != 0 &&
-			    strcasecmp("none", optarg) != 0 &&
-			    strcasecmp("no", optarg) != 0)
-				errx(2, getstr(3), "--color");
-			break;
-#ifndef WITHOUT_GZIP
-		case DECOMPRESS_OPT:
-			filebehave = FILE_GZIP;
-			break;
-#endif
-		case LABEL_OPT:
-			label = optarg;
-			break;
-		case LINEBUF_OPT:
-			lbflag = true;
-			break;
-		case R_INCLUDE_OPT:
-			finclude = true;
-			add_fpattern(optarg, INCL_PAT);
-			break;
-		case R_EXCLUDE_OPT:
-			fexclude = true;
-			add_fpattern(optarg, EXCL_PAT);
-			break;
-		case R_DINCLUDE_OPT:
-			dinclude = true;
-			add_dpattern(optarg, INCL_PAT);
-			break;
-		case R_DEXCLUDE_OPT:
-			dexclude = true;
-			add_dpattern(optarg, EXCL_PAT);
-			break;
-		case HELP_OPT:
-		default:
-			usage();
-		}
-		lastc = c;
-		newarg = optind != prevoptind;
-		prevoptind = optind;
-	}
-	aargc -= optind;
-	aargv += optind;
-
-	/* Fail if we don't have any pattern */
-	if (aargc == 0 && needpattern)
-		usage();
-
-	/* Process patterns from command line */
-	if (aargc != 0 && needpattern) {
-		add_pattern(*aargv, strlen(*aargv));
-		--aargc;
-		++aargv;
-	}
-
-	switch (grepbehave) {
-	case GREP_FIXED:
-	case GREP_BASIC:
-		break;
-	case GREP_EXTENDED:
-		cflags |= REG_EXTENDED;
-		break;
-	default:
-		/* NOTREACHED */
-		usage();
-	}
-
-	fg_pattern = grep_calloc(patterns, sizeof(*fg_pattern));
-	r_pattern = grep_calloc(patterns, sizeof(*r_pattern));
-/*
- * XXX: fgrepcomp() and fastcomp() are workarounds for regexec() performance.
- * Optimizations should be done there.
- */
-		/* Check if cheating is allowed (always is for fgrep). */
-	if (grepbehave == GREP_FIXED) {
-		for (i = 0; i < patterns; ++i)
-			fgrepcomp(&fg_pattern[i], pattern[i]);
-	} else {
-		for (i = 0; i < patterns; ++i) {
-			if (fastcomp(&fg_pattern[i], pattern[i])) {
-				/* Fall back to full regex library */
-				c = regcomp(&r_pattern[i], pattern[i], cflags);
-				if (c != 0) {
-					regerror(c, &r_pattern[i], re_error,
-					    RE_ERROR_BUF);
-					errx(2, "%s", re_error);
-				}
-			}
-		}
-	}
-
-	if (lbflag) {
-#ifdef _IOLBF
-		setvbuf(stdout, NULL, _IOLBF, 0);
-#else
-		setlinebuf(stdout);
-#endif
-	}
-
-	if ((aargc == 0 || aargc == 1) && !Hflag)
-		hflag = true;
-
-	if (aargc == 0)
-		exit(!procfile("-"));
-
-	if (dirbehave == DIR_RECURSE)
-		c = grep_tree(aargv);
-	else
-		for (c = 0; aargc--; ++aargv) {
-			if ((finclude || fexclude) && !file_matching(*aargv))
-				continue;
-			c+= procfile(*aargv);
-		}
-
-#ifndef WITHOUT_NLS
-	catclose(catalog);
-#endif
-
-	/* Find out the correct return value according to the
-	   results and the command line option. */
-	exit(c ? (notfound ? (qflag ? 0 : 2) : 0) : (notfound ? 2 : 1));
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/grep.h b/toolbox/upstream-netbsd/usr.bin/grep/grep.h
deleted file mode 100644
index b7ef7fa..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/grep.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*	$NetBSD: grep.h,v 1.10 2018/08/12 09:03:21 christos Exp $	*/
-/*	$OpenBSD: grep.h,v 1.15 2010/04/05 03:03:55 tedu Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/grep.h 211496 2010-08-19 09:28:59Z des $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (c) 2008-2009 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef WITHOUT_BZ2
-#include <bzlib.h>
-#endif
-#include <limits.h>
-#include <regex.h>
-#include <stdbool.h>
-#include <stdio.h>
-#ifndef WITHOUT_GZIP
-#include <zlib.h>
-#endif
-
-#ifdef WITHOUT_NLS
-#define getstr(n)	 errstr[n]
-#else
-#include <nl_types.h>
-
-extern nl_catd		 catalog;
-#define getstr(n)	 catgets(catalog, 1, n, errstr[n])
-#endif
-
-extern const char		*errstr[];
-
-#define VERSION		"2.5.1-FreeBSD"
-
-#define GREP_FIXED	0
-#define GREP_BASIC	1
-#define GREP_EXTENDED	2
-
-#define BINFILE_BIN	0
-#define BINFILE_SKIP	1
-#define BINFILE_TEXT	2
-
-#define FILE_STDIO	0
-#define FILE_GZIP	1
-#define FILE_BZIP	2
-
-#define DIR_READ	0
-#define DIR_SKIP	1
-#define DIR_RECURSE	2
-
-#define DEV_READ	0
-#define DEV_SKIP	1
-
-#define LINK_READ	0
-#define LINK_EXPLICIT	1
-#define LINK_SKIP	2
-
-#define EXCL_PAT	0
-#define INCL_PAT	1
-
-#define MAX_LINE_MATCHES	32
-
-struct file {
-	int		 fd;
-	bool		 binary;
-};
-
-struct str {
-	off_t		 off;
-	size_t		 len;
-	char		*dat;
-	char		*file;
-	int		 line_no;
-};
-
-struct epat {
-	char		*pat;
-	int		 mode;
-};
-
-typedef struct {
-	size_t		 len;
-	unsigned char	*pattern;
-	int		 qsBc[UCHAR_MAX + 1];
-	/* flags */
-	bool		 bol;
-	bool		 eol;
-	bool		 reversed;
-	bool		 word;
-} fastgrep_t;
-
-/* Flags passed to regcomp() and regexec() */
-extern int	 cflags, eflags;
-
-/* Command line flags */
-extern bool	 Eflag, Fflag, Gflag, Hflag, Lflag,
-		 bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag,
-		 qflag, sflag, vflag, wflag, xflag;
-extern bool	 dexclude, dinclude, fexclude, finclude, lbflag, nullflag, nulldataflag;
-extern unsigned char line_sep;
-extern unsigned long long Aflag, Bflag, mcount;
-extern char	*label;
-extern const char *color;
-extern int	 binbehave, devbehave, dirbehave, filebehave, grepbehave, linkbehave;
-
-extern bool	 notfound;
-extern int	 tail;
-extern unsigned int dpatterns, fpatterns, patterns;
-extern char    **pattern;
-extern struct epat *dpattern, *fpattern;
-extern regex_t	*er_pattern, *r_pattern;
-extern fastgrep_t *fg_pattern;
-
-/* For regex errors  */
-#define RE_ERROR_BUF	512
-extern char	 re_error[RE_ERROR_BUF + 1];	/* Seems big enough */
-
-/* util.c */
-bool	 file_matching(const char *fname);
-int	 procfile(const char *fn);
-int	 grep_tree(char **argv);
-void	*grep_malloc(size_t size);
-void	*grep_calloc(size_t nmemb, size_t size);
-void	*grep_realloc(void *ptr, size_t size);
-char	*grep_strdup(const char *str);
-void	 printline(struct str *line, int sep, regmatch_t *matches, int m);
-
-/* queue.c */
-void	 enqueue(struct str *x);
-void	 printqueue(void);
-void	 clearqueue(void);
-
-/* file.c */
-void		 grep_close(struct file *f);
-struct file	*grep_open(const char *path);
-char		*grep_fgetln(struct file *f, size_t *len);
-
-/* fastgrep.c */
-int		 fastcomp(fastgrep_t *, const char *);
-void		 fgrepcomp(fastgrep_t *, const char *);
-int		 grep_search(fastgrep_t *, const unsigned char *, size_t, regmatch_t *);
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/queue.c b/toolbox/upstream-netbsd/usr.bin/grep/queue.c
deleted file mode 100644
index e3c6be1..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/queue.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*	$NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/queue.c 211496 2010-08-19 09:28:59Z des $	*/
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * A really poor man's queue.  It does only what it has to and gets out of
- * Dodge.  It is used in place of <sys/queue.h> to get a better performance.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: queue.c,v 1.5 2011/08/31 16:24:57 plunky Exp $");
-
-#include <sys/param.h>
-#include <sys/queue.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "grep.h"
-
-struct qentry {
-	STAILQ_ENTRY(qentry)	list;
-	struct str	 	data;
-};
-
-static STAILQ_HEAD(, qentry)	queue = STAILQ_HEAD_INITIALIZER(queue);
-static unsigned long long	count;
-
-static struct qentry	*dequeue(void);
-
-void
-enqueue(struct str *x)
-{
-	struct qentry *item;
-
-	item = grep_malloc(sizeof(struct qentry));
-	item->data.dat = grep_malloc(sizeof(char) * x->len);
-	item->data.len = x->len;
-	item->data.line_no = x->line_no;
-	item->data.off = x->off;
-	memcpy(item->data.dat, x->dat, x->len);
-	item->data.file = x->file;
-
-	STAILQ_INSERT_TAIL(&queue, item, list);
-
-	if (++count > Bflag) {
-		item = dequeue();
-		free(item->data.dat);
-		free(item);
-	}
-}
-
-static struct qentry *
-dequeue(void)
-{
-	struct qentry *item;
-
-	item = STAILQ_FIRST(&queue);
-	if (item == NULL)
-		return (NULL);
-
-	STAILQ_REMOVE_HEAD(&queue, list);
-	--count;
-	return (item);
-}
-
-void
-printqueue(void)
-{
-	struct qentry *item;
-
-	while ((item = dequeue()) != NULL) {
-		printline(&item->data, '-', NULL, 0);
-		free(item->data.dat);
-		free(item);
-	}
-}
-
-void
-clearqueue(void)
-{
-	struct qentry *item;
-
-	while ((item = dequeue()) != NULL) {
-		free(item->data.dat);
-		free(item);
-	}
-}
diff --git a/toolbox/upstream-netbsd/usr.bin/grep/util.c b/toolbox/upstream-netbsd/usr.bin/grep/util.c
deleted file mode 100644
index a3c9e4c..0000000
--- a/toolbox/upstream-netbsd/usr.bin/grep/util.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*	$NetBSD: util.c,v 1.19 2018/02/05 22:14:26 mrg Exp $	*/
-/*	$FreeBSD: head/usr.bin/grep/util.c 211496 2010-08-19 09:28:59Z des $	*/
-/*	$OpenBSD: util.c,v 1.39 2010/07/02 22:18:03 tedu Exp $	*/
-
-/*-
- * Copyright (c) 1999 James Howard and Dag-Erling Coïdan Smørgrav
- * Copyright (C) 2008-2010 Gabor Kovesdan <gabor@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if HAVE_NBTOOL_CONFIG_H
-#include "nbtool_config.h"
-#endif
-
-#include <sys/cdefs.h>
-__RCSID("$NetBSD: util.c,v 1.19 2018/02/05 22:14:26 mrg Exp $");
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fnmatch.h>
-#include <fts.h>
-#include <libgen.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include "grep.h"
-
-static bool	 first, first_global = true;
-static unsigned long long since_printed;
-
-static int	 procline(struct str *l, int);
-
-bool
-file_matching(const char *fname)
-{
-	char *fname_base, *fname_copy;
-	unsigned int i;
-	bool ret;
-
-	ret = finclude ? false : true;
-	fname_copy = grep_strdup(fname);
-	fname_base = basename(fname_copy);
-
-	for (i = 0; i < fpatterns; ++i) {
-		if (fnmatch(fpattern[i].pat, fname, 0) == 0 ||
-		    fnmatch(fpattern[i].pat, fname_base, 0) == 0) {
-			if (fpattern[i].mode == EXCL_PAT) {
-				free(fname_copy);
-				return (false);
-			} else
-				ret = true;
-		}
-	}
-	free(fname_copy);
-	return (ret);
-}
-
-static inline bool
-dir_matching(const char *dname)
-{
-	unsigned int i;
-	bool ret;
-
-	ret = dinclude ? false : true;
-
-	for (i = 0; i < dpatterns; ++i) {
-		if (dname != NULL &&
-		    fnmatch(dname, dpattern[i].pat, 0) == 0) {
-			if (dpattern[i].mode == EXCL_PAT)
-				return (false);
-			else
-				ret = true;
-		}
-	}
-	return (ret);
-}
-
-/*
- * Processes a directory when a recursive search is performed with
- * the -R option.  Each appropriate file is passed to procfile().
- */
-int
-grep_tree(char **argv)
-{
-	FTS *fts;
-	FTSENT *p;
-	char *d, *dir = NULL;
-	int c, fts_flags;
-	bool ok;
-
-	c = fts_flags = 0;
-
-	switch(linkbehave) {
-	case LINK_EXPLICIT:
-		fts_flags = FTS_COMFOLLOW;
-		break;
-	case LINK_SKIP:
-		fts_flags = FTS_PHYSICAL;
-		break;
-	default:
-		fts_flags = FTS_LOGICAL;
-			
-	}
-
-	fts_flags |= FTS_NOSTAT | FTS_NOCHDIR;
-
-	if (!(fts = fts_open(argv, fts_flags, NULL)))
-		err(2, "fts_open");
-	while ((p = fts_read(fts)) != NULL) {
-		switch (p->fts_info) {
-		case FTS_DNR:
-			/* FALLTHROUGH */
-		case FTS_ERR:
-			errx(2, "%s: %s", p->fts_path, strerror(p->fts_errno));
-			break;
-		case FTS_D:
-			/* FALLTHROUGH */
-		case FTS_DP:
-			break;
-		case FTS_DC:
-			/* Print a warning for recursive directory loop */
-			warnx("warning: %s: recursive directory loop",
-				p->fts_path);
-			break;
-		default:
-			/* Check for file exclusion/inclusion */
-			ok = true;
-			if (dexclude || dinclude) {
-				if ((d = strrchr(p->fts_path, '/')) != NULL) {
-					dir = grep_malloc(sizeof(char) *
-					    (d - p->fts_path + 1));
-					memcpy(dir, p->fts_path,
-					    d - p->fts_path);
-					dir[d - p->fts_path] = '\0';
-				}
-				ok = dir_matching(dir);
-				free(dir);
-				dir = NULL;
-			}
-			if (fexclude || finclude)
-				ok &= file_matching(p->fts_path);
-
-			if (ok)
-				c += procfile(p->fts_path);
-			break;
-		}
-	}
-
-	fts_close(fts);
-	return (c);
-}
-
-/*
- * Opens a file and processes it.  Each file is processed line-by-line
- * passing the lines to procline().
- */
-int
-procfile(const char *fn)
-{
-	struct file *f;
-	struct stat sb;
-	struct str ln;
-	mode_t s;
-	int c, t;
-
-	if (mflag && (mcount <= 0))
-		return (0);
-
-	if (strcmp(fn, "-") == 0) {
-		fn = label != NULL ? label : getstr(1);
-		f = grep_open(NULL);
-	} else {
-		if (!stat(fn, &sb)) {
-			/* Check if we need to process the file */
-			s = sb.st_mode & S_IFMT;
-			if (s == S_IFDIR && dirbehave == DIR_SKIP)
-				return (0);
-			if ((s == S_IFIFO || s == S_IFCHR || s == S_IFBLK
-				|| s == S_IFSOCK) && devbehave == DEV_SKIP)
-					return (0);
-		}
-		f = grep_open(fn);
-	}
-	if (f == NULL) {
-		if (!sflag)
-			warn("%s", fn);
-		if (errno == ENOENT)
-			notfound = true;
-		return (0);
-	}
-
-	ln.file = grep_malloc(strlen(fn) + 1);
-	strcpy(ln.file, fn);
-	ln.line_no = 0;
-	ln.len = 0;
-	tail = 0;
-	ln.off = -1;
-
-	for (first = true, c = 0;  c == 0 || !(lflag || qflag); ) {
-		ln.off += ln.len + 1;
-		if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL || ln.len == 0)
-			break;
-		if (ln.len > 0 && ln.dat[ln.len - 1] == line_sep)
-			--ln.len;
-		ln.line_no++;
-
-		/* Return if we need to skip a binary file */
-		if (f->binary && binbehave == BINFILE_SKIP) {
-			grep_close(f);
-			free(ln.file);
-			free(f);
-			return (0);
-		}
-		/* Process the file line-by-line */
-		t = procline(&ln, f->binary);
-		c += t;
-
-		/* Count the matches if we have a match limit */
-		if (mflag) {
-			mcount -= t;
-			if (mcount <= 0)
-				break;
-		}
-	}
-	if (Bflag > 0)
-		clearqueue();
-	grep_close(f);
-
-	if (cflag) {
-		if (!hflag)
-			printf("%s:", ln.file);
-		printf("%u%c", c, line_sep);
-	}
-	if (lflag && !qflag && c != 0)
-		printf("%s%c", fn, line_sep);
-	if (Lflag && !qflag && c == 0)
-		printf("%s%c", fn, line_sep);
-	if (c && !cflag && !lflag && !Lflag &&
-	    binbehave == BINFILE_BIN && f->binary && !qflag)
-		printf(getstr(8), fn);
-
-	free(ln.file);
-	free(f);
-	return (c);
-}
-
-#define iswword(x)	(iswalnum((x)) || (x) == L'_')
-
-/*
- * Processes a line comparing it with the specified patterns.  Each pattern
- * is looped to be compared along with the full string, saving each and every
- * match, which is necessary to colorize the output and to count the
- * matches.  The matching lines are passed to printline() to display the
- * appropriate output.
- */
-static int
-procline(struct str *l, int nottext)
-{
-	regmatch_t matches[MAX_LINE_MATCHES];
-	regmatch_t pmatch;
-	size_t st = 0;
-	unsigned int i;
-	int c = 0, m = 0, r = 0;
-
-	/* Loop to process the whole line */
-	while (st <= l->len) {
-		pmatch.rm_so = st;
-		pmatch.rm_eo = l->len;
-
-		/* Loop to compare with all the patterns */
-		for (i = 0; i < patterns; i++) {
-/*
- * XXX: grep_search() is a workaround for speed up and should be
- * removed in the future.  See fastgrep.c.
- */
-			if (fg_pattern[i].pattern) {
-				r = grep_search(&fg_pattern[i],
-				    (unsigned char *)l->dat,
-				    l->len, &pmatch);
-				r = (r == 0) ? 0 : REG_NOMATCH;
-				st = pmatch.rm_eo;
-			} else {
-				r = regexec(&r_pattern[i], l->dat, 1,
-				    &pmatch, eflags);
-				r = (r == 0) ? 0 : REG_NOMATCH;
-				st = pmatch.rm_eo;
-			}
-			if (r == REG_NOMATCH)
-				continue;
-			/* Check for full match */
-			if (xflag &&
-			    (pmatch.rm_so != 0 ||
-			     (size_t)pmatch.rm_eo != l->len))
-				continue;
-			/* Check for whole word match */
-			if (fg_pattern[i].word && pmatch.rm_so != 0) {
-				wchar_t wbegin, wend;
-
-				wbegin = wend = L' ';
-				if (pmatch.rm_so != 0 &&
-				    sscanf(&l->dat[pmatch.rm_so - 1],
-				    "%lc", &wbegin) != 1)
-					continue;
-				if ((size_t)pmatch.rm_eo != l->len &&
-				    sscanf(&l->dat[pmatch.rm_eo],
-				    "%lc", &wend) != 1)
-					continue;
-				if (iswword(wbegin) || iswword(wend))
-					continue;
-			}
-			c = 1;
-			if (m < MAX_LINE_MATCHES)
-				matches[m++] = pmatch;
-			/* matches - skip further patterns */
-			if ((color != NULL && !oflag) || qflag || lflag)
-				break;
-		}
-
-		if (vflag) {
-			c = !c;
-			break;
-		}
-		/* One pass if we are not recording matches */
-		if ((color != NULL && !oflag) || qflag || lflag)
-			break;
-
-		if (st == (size_t)pmatch.rm_so)
-			break; 	/* No matches */
-	}
-
-	if (c && binbehave == BINFILE_BIN && nottext)
-		return (c); /* Binary file */
-
-	/* Dealing with the context */
-	if ((tail || c) && !cflag && !qflag && !lflag && !Lflag) {
-		if (c) {
-			if ((Aflag || Bflag) && !first_global &&
-			    (first || since_printed > Bflag))
-				printf("--\n");
-			tail = Aflag;
-			if (Bflag > 0)
-				printqueue();
-			printline(l, ':', matches, m);
-		} else {
-			printline(l, '-', matches, m);
-			tail--;
-		}
-		first = false;
-		first_global = false;
-		since_printed = 0;
-	} else {
-		if (Bflag)
-			enqueue(l);
-		since_printed++;
-	}
-	return (c);
-}
-
-/*
- * Safe malloc() for internal use.
- */
-void *
-grep_malloc(size_t size)
-{
-	void *ptr;
-
-	if ((ptr = malloc(size)) == NULL)
-		err(2, "malloc");
-	return (ptr);
-}
-
-/*
- * Safe calloc() for internal use.
- */
-void *
-grep_calloc(size_t nmemb, size_t size)
-{
-	void *ptr;
-
-	if ((ptr = calloc(nmemb, size)) == NULL)
-		err(2, "calloc");
-	return (ptr);
-}
-
-/*
- * Safe realloc() for internal use.
- */
-void *
-grep_realloc(void *ptr, size_t size)
-{
-
-	if ((ptr = realloc(ptr, size)) == NULL)
-		err(2, "realloc");
-	return (ptr);
-}
-
-/*
- * Safe strdup() for internal use.
- */
-char *
-grep_strdup(const char *str)
-{
-	char *ret;
-
-	if ((ret = strdup(str)) == NULL)
-		err(2, "strdup");
-	return (ret);
-}
-
-/*
- * Prints a matching line according to the command line options.
- */
-void
-printline(struct str *line, int sep, regmatch_t *matches, int m)
-{
-	size_t a = 0;
-	int i, n = 0;
-
-	if (!hflag) {
-		if (nullflag == 0)
-			fputs(line->file, stdout);
-		else {
-			printf("%s", line->file);
-			putchar(0);
-		}
-		++n;
-	}
-	if (nflag) {
-		if (n > 0)
-			putchar(sep);
-		printf("%d", line->line_no);
-		++n;
-	}
-	if (bflag) {
-		if (n > 0)
-			putchar(sep);
-		printf("%lld", (long long)line->off);
-		++n;
-	}
-	if (n)
-		putchar(sep);
-	/* --color and -o */
-	if ((oflag || color) && m > 0) {
-		for (i = 0; i < m; i++) {
-			if (!oflag)
-				fwrite(line->dat + a, matches[i].rm_so - a, 1,
-				    stdout);
-			if (color) 
-				fprintf(stdout, "\33[%sm\33[K", color);
-
-			fwrite(line->dat + matches[i].rm_so, 
-			    matches[i].rm_eo - matches[i].rm_so, 1,
-			    stdout);
-
-			if (color) 
-				fprintf(stdout, "\33[m\33[K");
-			a = matches[i].rm_eo;
-			if (oflag)
-				putchar('\n');
-		}
-		if (!oflag) {
-			if (line->len - a > 0)
-				fwrite(line->dat + a, line->len - a, 1, stdout);
-			putchar(line_sep);
-		}
-	} else {
-		fwrite(line->dat, line->len, 1, stdout);
-		putchar(line_sep);
-	}
-}
diff --git a/trusty/OWNERS b/trusty/OWNERS
index e807d71..1fb473e 100644
--- a/trusty/OWNERS
+++ b/trusty/OWNERS
@@ -2,6 +2,8 @@
 dkrahn@google.com
 drewry@google.com
 gmar@google.com
+mmaurer@google.com
 ncbray@google.com
-rpere@google.com
 swillden@google.com
+trong@google.com
+wenhaowang@google.com
diff --git a/trusty/gatekeeper/Android.bp b/trusty/gatekeeper/Android.bp
index 65b271a..e553af1 100644
--- a/trusty/gatekeeper/Android.bp
+++ b/trusty/gatekeeper/Android.bp
@@ -1,4 +1,3 @@
-//
 // Copyright (C) 2015 The Android Open-Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,14 +19,15 @@
 // to only building on ARM if they include assembly. Individual makefiles
 // are responsible for having their own logic, for fine-grained control.
 
-cc_library_shared {
-    name: "gatekeeper.trusty",
+cc_binary {
+    name: "android.hardware.gatekeeper@1.0-service.trusty",
+    defaults: ["hidl_defaults"],
     vendor: true,
-
     relative_install_path: "hw",
+    init_rc: ["android.hardware.gatekeeper@1.0-service.trusty.rc"],
 
     srcs: [
-        "module.cpp",
+        "service.cpp",
         "trusty_gatekeeper_ipc.c",
         "trusty_gatekeeper.cpp",
     ],
@@ -39,10 +39,15 @@
     ],
 
     shared_libs: [
+        "android.hardware.gatekeeper@1.0",
+        "libbase",
+        "libhidlbase",
         "libgatekeeper",
+        "libutils",
         "liblog",
         "libcutils",
         "libtrusty",
     ],
-    header_libs: ["libhardware_headers"],
+
+    vintf_fragments: ["android.hardware.gatekeeper@1.0-service.trusty.xml"],
 }
diff --git a/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.rc b/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.rc
new file mode 100644
index 0000000..5413a6c
--- /dev/null
+++ b/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.rc
@@ -0,0 +1,4 @@
+service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.trusty
+    class hal
+    user system
+    group system
diff --git a/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.xml b/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.xml
new file mode 100644
index 0000000..19714a8
--- /dev/null
+++ b/trusty/gatekeeper/android.hardware.gatekeeper@1.0-service.trusty.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.gatekeeper</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+        <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/trusty/gatekeeper/module.cpp b/trusty/gatekeeper/module.cpp
deleted file mode 100644
index 0ee3c2f..0000000
--- a/trusty/gatekeeper/module.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2015 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 <hardware/hardware.h>
-
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-#include "trusty_gatekeeper.h"
-
-using gatekeeper::TrustyGateKeeperDevice;
-
-static int trusty_gatekeeper_open(const hw_module_t *module, const char *name,
-        hw_device_t **device) {
-
-    if (strcmp(name, HARDWARE_GATEKEEPER) != 0) {
-        return -EINVAL;
-    }
-
-    TrustyGateKeeperDevice *gatekeeper = new TrustyGateKeeperDevice(module);
-    if (gatekeeper == NULL) return -ENOMEM;
-    *device = gatekeeper->hw_device();
-
-    return 0;
-}
-
-static struct hw_module_methods_t gatekeeper_module_methods = {
-    .open = trusty_gatekeeper_open,
-};
-
-struct gatekeeper_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
-    .common = {
-        .tag = HARDWARE_MODULE_TAG,
-        .module_api_version = GATEKEEPER_MODULE_API_VERSION_0_1,
-        .hal_api_version = HARDWARE_HAL_API_VERSION,
-        .id = GATEKEEPER_HARDWARE_MODULE_ID,
-        .name = "Trusty GateKeeper HAL",
-        .author = "The Android Open Source Project",
-        .methods = &gatekeeper_module_methods,
-        .dso = 0,
-        .reserved = {}
-    },
-};
diff --git a/trusty/gatekeeper/service.cpp b/trusty/gatekeeper/service.cpp
new file mode 100644
index 0000000..c5ee488
--- /dev/null
+++ b/trusty/gatekeeper/service.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "android.hardware.gatekeeper@1.0-service.trusty"
+
+#include <android-base/logging.h>
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+
+#include <hidl/LegacySupport.h>
+
+#include "trusty_gatekeeper.h"
+
+// Generated HIDL files
+using android::hardware::gatekeeper::V1_0::IGatekeeper;
+using gatekeeper::TrustyGateKeeperDevice;
+
+int main() {
+    ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
+    android::sp<TrustyGateKeeperDevice> gatekeeper(new TrustyGateKeeperDevice());
+    auto status = gatekeeper->registerAsService();
+    if (status != android::OK) {
+        LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (trusty) (" << status << ")";
+    }
+
+    android::hardware::joinRpcThreadpool();
+    return -1;  // Should never get here.
+}
diff --git a/trusty/gatekeeper/trusty_gatekeeper.cpp b/trusty/gatekeeper/trusty_gatekeeper.cpp
index b3fbfa9..d149664 100644
--- a/trusty/gatekeeper/trusty_gatekeeper.cpp
+++ b/trusty/gatekeeper/trusty_gatekeeper.cpp
@@ -16,147 +16,131 @@
 
 #define LOG_TAG "TrustyGateKeeper"
 
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include <type_traits>
-
-#include <log/log.h>
+#include <android-base/logging.h>
+#include <limits>
 
 #include "trusty_gatekeeper.h"
 #include "trusty_gatekeeper_ipc.h"
 #include "gatekeeper_ipc.h"
 
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
+using ::gatekeeper::EnrollRequest;
+using ::gatekeeper::EnrollResponse;
+using ::gatekeeper::ERROR_INVALID;
+using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED;
+using ::gatekeeper::ERROR_NONE;
+using ::gatekeeper::ERROR_RETRY;
+using ::gatekeeper::SizedBuffer;
+using ::gatekeeper::VerifyRequest;
+using ::gatekeeper::VerifyResponse;
+
 namespace gatekeeper {
 
-const uint32_t SEND_BUF_SIZE = 8192;
-const uint32_t RECV_BUF_SIZE = 8192;
+constexpr const uint32_t SEND_BUF_SIZE = 8192;
+constexpr const uint32_t RECV_BUF_SIZE = 8192;
 
-TrustyGateKeeperDevice::TrustyGateKeeperDevice(const hw_module_t *module) {
-#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
-    static_assert(std::is_standard_layout<TrustyGateKeeperDevice>::value,
-                  "TrustyGateKeeperDevice must be standard layout");
-    static_assert(offsetof(TrustyGateKeeperDevice, device_) == 0,
-                  "device_ must be the first member of TrustyGateKeeperDevice");
-    static_assert(offsetof(TrustyGateKeeperDevice, device_.common) == 0,
-                  "common must be the first member of gatekeeper_device");
-#else
-    assert(reinterpret_cast<gatekeeper_device_t *>(this) == &device_);
-    assert(reinterpret_cast<hw_device_t *>(this) == &(device_.common));
-#endif
-
-    memset(&device_, 0, sizeof(device_));
-    device_.common.tag = HARDWARE_DEVICE_TAG;
-    device_.common.version = 1;
-    device_.common.module = const_cast<hw_module_t *>(module);
-    device_.common.close = close_device;
-
-    device_.enroll = enroll;
-    device_.verify = verify;
-    device_.delete_user = nullptr;
-    device_.delete_all_users = nullptr;
-
+TrustyGateKeeperDevice::TrustyGateKeeperDevice() {
     int rc = trusty_gatekeeper_connect();
     if (rc < 0) {
-        ALOGE("Error initializing trusty session: %d", rc);
+        LOG(ERROR) << "Error initializing trusty session: " << rc;
     }
 
     error_ = rc;
-
-}
-
-hw_device_t* TrustyGateKeeperDevice::hw_device() {
-    return &device_.common;
-}
-
-int TrustyGateKeeperDevice::close_device(hw_device_t* dev) {
-    delete reinterpret_cast<TrustyGateKeeperDevice *>(dev);
-    return 0;
 }
 
 TrustyGateKeeperDevice::~TrustyGateKeeperDevice() {
     trusty_gatekeeper_disconnect();
 }
 
-int TrustyGateKeeperDevice::Enroll(uint32_t uid, const uint8_t *current_password_handle,
-        uint32_t current_password_handle_length, const uint8_t *current_password,
-        uint32_t current_password_length, const uint8_t *desired_password,
-        uint32_t desired_password_length, uint8_t **enrolled_password_handle,
-        uint32_t *enrolled_password_handle_length) {
-
-    if (error_ != 0) {
-        return error_;
-    }
-
-    SizedBuffer desired_password_buffer(desired_password_length);
-    memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length);
-
-    SizedBuffer current_password_handle_buffer(current_password_handle_length);
-    if (current_password_handle) {
-        memcpy(current_password_handle_buffer.buffer.get(), current_password_handle,
-                current_password_handle_length);
-    }
-
-    SizedBuffer current_password_buffer(current_password_length);
-    if (current_password) {
-        memcpy(current_password_buffer.buffer.get(), current_password, current_password_length);
-    }
-
-    EnrollRequest request(uid, &current_password_handle_buffer, &desired_password_buffer,
-            &current_password_buffer);
-    EnrollResponse response;
-
-    gatekeeper_error_t error = Send(request, &response);
-
-    if (error == ERROR_RETRY) {
-        return response.retry_timeout;
-    } else if (error != ERROR_NONE) {
-        return -EINVAL;
-    }
-
-    *enrolled_password_handle = response.enrolled_password_handle.buffer.release();
-    *enrolled_password_handle_length = response.enrolled_password_handle.length;
-
-
-    return 0;
+SizedBuffer hidl_vec2sized_buffer(const hidl_vec<uint8_t>& vec) {
+    if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) return {};
+    auto dummy = new uint8_t[vec.size()];
+    std::copy(vec.begin(), vec.end(), dummy);
+    return {dummy, static_cast<uint32_t>(vec.size())};
 }
 
-int TrustyGateKeeperDevice::Verify(uint32_t uid, uint64_t challenge,
-        const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
-        const uint8_t *provided_password, uint32_t provided_password_length,
-        uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
+Return<void> TrustyGateKeeperDevice::enroll(uint32_t uid,
+                                            const hidl_vec<uint8_t>& currentPasswordHandle,
+                                            const hidl_vec<uint8_t>& currentPassword,
+                                            const hidl_vec<uint8_t>& desiredPassword,
+                                            enroll_cb _hidl_cb) {
     if (error_ != 0) {
-        return error_;
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+        return {};
     }
 
-    SizedBuffer password_handle_buffer(enrolled_password_handle_length);
-    memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle,
-            enrolled_password_handle_length);
-    SizedBuffer provided_password_buffer(provided_password_length);
-    memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length);
+    if (desiredPassword.size() == 0) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+        return {};
+    }
 
-    VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer);
+    EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle),
+                          hidl_vec2sized_buffer(desiredPassword),
+                          hidl_vec2sized_buffer(currentPassword));
+    EnrollResponse response;
+    auto error = Send(request, &response);
+    if (error != ERROR_NONE) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+    } else if (response.error == ERROR_RETRY) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
+    } else if (response.error != ERROR_NONE) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+    } else {
+        hidl_vec<uint8_t> new_handle(response.enrolled_password_handle.Data<uint8_t>(),
+                                     response.enrolled_password_handle.Data<uint8_t>() +
+                                             response.enrolled_password_handle.size());
+        _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle});
+    }
+    return {};
+}
+
+Return<void> TrustyGateKeeperDevice::verify(
+        uint32_t uid, uint64_t challenge,
+        const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
+        const ::android::hardware::hidl_vec<uint8_t>& providedPassword, verify_cb _hidl_cb) {
+    if (error_ != 0) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+        return {};
+    }
+
+    if (enrolledPasswordHandle.size() == 0) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+        return {};
+    }
+
+    VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle),
+                          hidl_vec2sized_buffer(providedPassword));
     VerifyResponse response;
 
-    gatekeeper_error_t error = Send(request, &response);
+    auto error = Send(request, &response);
+    if (error != ERROR_NONE) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+    } else if (response.error == ERROR_RETRY) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
+    } else if (response.error != ERROR_NONE) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+    } else {
+        hidl_vec<uint8_t> auth_token(
+                response.auth_token.Data<uint8_t>(),
+                response.auth_token.Data<uint8_t>() + response.auth_token.size());
 
-    if (error == ERROR_RETRY) {
-        return response.retry_timeout;
-    } else if (error != ERROR_NONE) {
-        return -EINVAL;
+        _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL
+                                            : GatekeeperStatusCode::STATUS_OK,
+                  response.retry_timeout, auth_token});
     }
+    return {};
+}
 
-    if (auth_token != NULL && auth_token_length != NULL) {
-       *auth_token = response.auth_token.buffer.release();
-       *auth_token_length = response.auth_token.length;
-    }
+Return<void> TrustyGateKeeperDevice::deleteUser(uint32_t /*uid*/, deleteUser_cb _hidl_cb) {
+    _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
+    return {};
+}
 
-    if (request_reenroll != NULL) {
-        *request_reenroll = response.request_reenroll;
-    }
-
-    return 0;
+Return<void> TrustyGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) {
+    _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
+    return {};
 }
 
 gatekeeper_error_t TrustyGateKeeperDevice::Send(uint32_t command, const GateKeeperMessage& request,
@@ -172,7 +156,7 @@
     uint32_t response_size = RECV_BUF_SIZE;
     int rc = trusty_gatekeeper_call(command, send_buf, request_size, recv_buf, &response_size);
     if (rc < 0) {
-        ALOGE("error (%d) calling gatekeeper TA", rc);
+        LOG(ERROR) << "error (" << rc << ") calling gatekeeper TA";
         return ERROR_INVALID;
     }
 
@@ -182,51 +166,4 @@
     return response->Deserialize(payload, payload + response_size);
 }
 
-static inline TrustyGateKeeperDevice *convert_device(const gatekeeper_device *dev) {
-    return reinterpret_cast<TrustyGateKeeperDevice *>(const_cast<gatekeeper_device *>(dev));
-}
-
-/* static */
-int TrustyGateKeeperDevice::enroll(const struct gatekeeper_device *dev, uint32_t uid,
-            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
-            const uint8_t *current_password, uint32_t current_password_length,
-            const uint8_t *desired_password, uint32_t desired_password_length,
-            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
-
-    if (dev == NULL ||
-            enrolled_password_handle == NULL || enrolled_password_handle_length == NULL ||
-            desired_password == NULL || desired_password_length == 0)
-        return -EINVAL;
-
-    // Current password and current password handle go together
-    if (current_password_handle == NULL || current_password_handle_length == 0 ||
-            current_password == NULL || current_password_length == 0) {
-        current_password_handle = NULL;
-        current_password_handle_length = 0;
-        current_password = NULL;
-        current_password_length = 0;
-    }
-
-    return convert_device(dev)->Enroll(uid, current_password_handle, current_password_handle_length,
-            current_password, current_password_length, desired_password, desired_password_length,
-            enrolled_password_handle, enrolled_password_handle_length);
-
-}
-
-/* static */
-int TrustyGateKeeperDevice::verify(const struct gatekeeper_device *dev, uint32_t uid,
-        uint64_t challenge, const uint8_t *enrolled_password_handle,
-        uint32_t enrolled_password_handle_length, const uint8_t *provided_password,
-        uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,
-        bool *request_reenroll) {
-
-    if (dev == NULL || enrolled_password_handle == NULL ||
-            provided_password == NULL) {
-        return -EINVAL;
-    }
-
-    return convert_device(dev)->Verify(uid, challenge, enrolled_password_handle,
-            enrolled_password_handle_length, provided_password, provided_password_length,
-            auth_token, auth_token_length, request_reenroll);
-}
 };
diff --git a/trusty/gatekeeper/trusty_gatekeeper.h b/trusty/gatekeeper/trusty_gatekeeper.h
index 2becc49..c0713f4 100644
--- a/trusty/gatekeeper/trusty_gatekeeper.h
+++ b/trusty/gatekeeper/trusty_gatekeeper.h
@@ -17,84 +17,34 @@
 #ifndef TRUSTY_GATEKEEPER_H
 #define TRUSTY_GATEKEEPER_H
 
-#include <hardware/gatekeeper.h>
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+#include <hidl/Status.h>
+
+#include <memory>
+
 #include <gatekeeper/gatekeeper_messages.h>
 
 #include "gatekeeper_ipc.h"
 
 namespace gatekeeper {
 
-class TrustyGateKeeperDevice {
-    public:
-
-    explicit TrustyGateKeeperDevice(const hw_module_t* module);
+class TrustyGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper {
+  public:
+    explicit TrustyGateKeeperDevice();
     ~TrustyGateKeeperDevice();
-
-    hw_device_t* hw_device();
-
     /**
      * Enrolls password_payload, which should be derived from a user selected pin or password,
      * with the authentication factor private key used only for enrolling authentication
      * factor data.
      *
      * Returns: 0 on success or an error code less than 0 on error.
-     * On error, enrolled_password will not be allocated.
-     */
-    int Enroll(uint32_t uid, const uint8_t *current_password_handle,
-            uint32_t current_password_handle_length, const uint8_t *current_password,
-            uint32_t current_password_length, const uint8_t *desired_password,
-            uint32_t desired_password_length, uint8_t **enrolled_password_handle,
-            uint32_t *enrolled_password_handle_length);
-
-    /**
-     * Verifies provided_password matches expected_password after enrolling
-     * with the authentication factor private key.
-     *
-     * Implementations of this module may retain the result of this call
-     * to attest to the recency of authentication.
-     *
-     * On success, writes the address of a verification token to verification_token,
-     *
-     * Returns: 0 on success or an error code less than 0 on error
-     * On error, verification token will not be allocated
-     */
-    int Verify(uint32_t uid, uint64_t challenge, const uint8_t *enrolled_password_handle,
-            uint32_t enrolled_password_handle_length, const uint8_t *provided_password,
-            uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,
-            bool *request_reenroll);
-
-    private:
-
-    gatekeeper_error_t Send(uint32_t command, const GateKeeperMessage& request,
-                           GateKeeperMessage* response);
-
-    gatekeeper_error_t Send(const EnrollRequest& request, EnrollResponse *response) {
-        return Send(GK_ENROLL, request, response);
-    }
-
-    gatekeeper_error_t Send(const VerifyRequest& request, VerifyResponse *response) {
-        return Send(GK_VERIFY, request, response);
-    }
-
-    // Static methods interfacing the HAL API with the TrustyGateKeeper device
-
-    /**
-     * Enrolls desired_password, which should be derived from a user selected pin or password,
-     * with the authentication factor private key used only for enrolling authentication
-     * factor data.
-     *
-     * If there was already a password enrolled, it should be provided in
-     * current_password_handle, along with the current password in current_password
-     * that should validate against current_password_handle.
-     *
-     * Returns: 0 on success or an error code less than 0 on error.
      * On error, enrolled_password_handle will not be allocated.
      */
-    static int enroll(const struct gatekeeper_device *dev, uint32_t uid,
-            const uint8_t *current_password_handle, uint32_t current_password_handle_length,
-            const uint8_t *current_password, uint32_t current_password_length,
-            const uint8_t *desired_password, uint32_t desired_password_length,
-            uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length);
+    ::android::hardware::Return<void> enroll(
+            uint32_t uid, const ::android::hardware::hidl_vec<uint8_t>& currentPasswordHandle,
+            const ::android::hardware::hidl_vec<uint8_t>& currentPassword,
+            const ::android::hardware::hidl_vec<uint8_t>& desiredPassword,
+            enroll_cb _hidl_cb) override;
 
     /**
      * Verifies provided_password matches enrolled_password_handle.
@@ -109,18 +59,32 @@
      * Returns: 0 on success or an error code less than 0 on error
      * On error, verification token will not be allocated
      */
-    static int verify(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge,
-            const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
-            const uint8_t *provided_password, uint32_t provided_password_length,
-            uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);
+    ::android::hardware::Return<void> verify(
+            uint32_t uid, uint64_t challenge,
+            const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
+            const ::android::hardware::hidl_vec<uint8_t>& providedPassword,
+            verify_cb _hidl_cb) override;
 
-    static int close_device(hw_device_t* dev);
+    ::android::hardware::Return<void> deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override;
 
-    gatekeeper_device device_;
+    ::android::hardware::Return<void> deleteAllUsers(deleteAllUsers_cb _hidl_cb) override;
+
+  private:
+    gatekeeper_error_t Send(uint32_t command, const GateKeeperMessage& request,
+                           GateKeeperMessage* response);
+
+    gatekeeper_error_t Send(const EnrollRequest& request, EnrollResponse *response) {
+        return Send(GK_ENROLL, request, response);
+    }
+
+    gatekeeper_error_t Send(const VerifyRequest& request, VerifyResponse *response) {
+        return Send(GK_VERIFY, request, response);
+    }
+
     int error_;
-
 };
-}
+
+}  // namespace gatekeeper
 
 #endif
 
diff --git a/trusty/keymaster/4.0/TrustyKeymaster4Device.cpp b/trusty/keymaster/4.0/TrustyKeymaster4Device.cpp
new file mode 100644
index 0000000..ec2ba12
--- /dev/null
+++ b/trusty/keymaster/4.0/TrustyKeymaster4Device.cpp
@@ -0,0 +1,614 @@
+/*
+ **
+ ** Copyright 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 "android.hardware.keymaster@4.0-impl.trusty"
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <authorization_set.h>
+#include <cutils/log.h>
+#include <keymaster/android_keymaster_messages.h>
+#include <trusty_keymaster/TrustyKeymaster4Device.h>
+#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
+
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
+using ::keymaster::AddEntropyRequest;
+using ::keymaster::AddEntropyResponse;
+using ::keymaster::AttestKeyRequest;
+using ::keymaster::AttestKeyResponse;
+using ::keymaster::AuthorizationSet;
+using ::keymaster::BeginOperationRequest;
+using ::keymaster::BeginOperationResponse;
+using ::keymaster::ExportKeyRequest;
+using ::keymaster::ExportKeyResponse;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
+using ::keymaster::GenerateKeyRequest;
+using ::keymaster::GenerateKeyResponse;
+using ::keymaster::GetKeyCharacteristicsRequest;
+using ::keymaster::GetKeyCharacteristicsResponse;
+using ::keymaster::ImportKeyRequest;
+using ::keymaster::ImportKeyResponse;
+using ::keymaster::UpdateOperationRequest;
+using ::keymaster::UpdateOperationResponse;
+using ::keymaster::ng::Tag;
+
+typedef ::android::hardware::keymaster::V3_0::Tag Tag3;
+using ::android::hardware::keymaster::V4_0::Constants;
+
+namespace keymaster {
+namespace V4_0 {
+namespace {
+
+inline keymaster_tag_t legacy_enum_conversion(const Tag value) {
+    return keymaster_tag_t(value);
+}
+inline Tag legacy_enum_conversion(const keymaster_tag_t value) {
+    return Tag(value);
+}
+inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+    return keymaster_purpose_t(value);
+}
+inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+    return keymaster_key_format_t(value);
+}
+
+inline SecurityLevel legacy_enum_conversion(const keymaster_security_level_t value) {
+    return static_cast<SecurityLevel>(value);
+}
+
+inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) {
+    return static_cast<hw_authenticator_type_t>(value);
+}
+
+inline ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+    return ErrorCode(value);
+}
+
+inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+    return keymaster_tag_get_type(tag);
+}
+
+/*
+ * injectAuthToken translates a KM4 authToken into a legacy AUTH_TOKEN tag
+ *
+ * Currently, system/keymaster's reference implementation only accepts this
+ * method for passing an auth token, so until that changes we need to
+ * translate to the old format.
+ */
+inline hidl_vec<KeyParameter> injectAuthToken(const hidl_vec<KeyParameter>& keyParamsBase,
+                                              const HardwareAuthToken& authToken) {
+    std::vector<KeyParameter> keyParams(keyParamsBase);
+    const size_t mac_len = static_cast<size_t>(Constants::AUTH_TOKEN_MAC_LENGTH);
+    /*
+     * mac.size() == 0 indicates no token provided, so we should not copy.
+     * mac.size() != mac_len means it is incompatible with the old
+     *   hw_auth_token_t structure. This is forbidden by spec, but to be safe
+     *   we only copy if mac.size() == mac_len, e.g. there is an authToken
+     *   with a hw_auth_token_t compatible MAC.
+     */
+    if (authToken.mac.size() == mac_len) {
+        KeyParameter p;
+        p.tag = static_cast<Tag>(Tag3::AUTH_TOKEN);
+        p.blob.resize(sizeof(hw_auth_token_t));
+
+        hw_auth_token_t* auth_token = reinterpret_cast<hw_auth_token_t*>(p.blob.data());
+        auth_token->version = 0;
+        auth_token->challenge = authToken.challenge;
+        auth_token->user_id = authToken.userId;
+        auth_token->authenticator_id = authToken.authenticatorId;
+        auth_token->authenticator_type =
+                htobe32(static_cast<uint32_t>(authToken.authenticatorType));
+        auth_token->timestamp = htobe64(authToken.timestamp);
+        static_assert(mac_len == sizeof(auth_token->hmac));
+        memcpy(auth_token->hmac, authToken.mac.data(), mac_len);
+        keyParams.push_back(p);
+    }
+
+    return hidl_vec<KeyParameter>(std::move(keyParams));
+}
+
+class KmParamSet : public keymaster_key_param_set_t {
+  public:
+    KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
+        params = new keymaster_key_param_t[keyParams.size()];
+        length = keyParams.size();
+        for (size_t i = 0; i < keyParams.size(); ++i) {
+            auto tag = legacy_enum_conversion(keyParams[i].tag);
+            switch (typeFromTag(tag)) {
+                case KM_ENUM:
+                case KM_ENUM_REP:
+                    params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+                    break;
+                case KM_UINT:
+                case KM_UINT_REP:
+                    params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+                    break;
+                case KM_ULONG:
+                case KM_ULONG_REP:
+                    params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+                    break;
+                case KM_DATE:
+                    params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+                    break;
+                case KM_BOOL:
+                    if (keyParams[i].f.boolValue)
+                        params[i] = keymaster_param_bool(tag);
+                    else
+                        params[i].tag = KM_TAG_INVALID;
+                    break;
+                case KM_BIGNUM:
+                case KM_BYTES:
+                    params[i] = keymaster_param_blob(tag, &keyParams[i].blob[0],
+                                                     keyParams[i].blob.size());
+                    break;
+                case KM_INVALID:
+                default:
+                    params[i].tag = KM_TAG_INVALID;
+                    /* just skip */
+                    break;
+            }
+        }
+    }
+    KmParamSet(KmParamSet&& other) noexcept
+        : keymaster_key_param_set_t{other.params, other.length} {
+        other.length = 0;
+        other.params = nullptr;
+    }
+    KmParamSet(const KmParamSet&) = delete;
+    ~KmParamSet() { delete[] params; }
+};
+
+inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
+    return result;
+}
+
+inline hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
+    return result;
+}
+
+inline hidl_vec<uint8_t> kmBuffer2hidlVec(const ::keymaster::Buffer& buf) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(buf.peek_read()), buf.available_read());
+    return result;
+}
+
+inline static hidl_vec<hidl_vec<uint8_t>> kmCertChain2Hidl(
+        const keymaster_cert_chain_t& cert_chain) {
+    hidl_vec<hidl_vec<uint8_t>> result;
+    if (!cert_chain.entry_count || !cert_chain.entries) return result;
+
+    result.resize(cert_chain.entry_count);
+    for (size_t i = 0; i < cert_chain.entry_count; ++i) {
+        result[i] = kmBlob2hidlVec(cert_chain.entries[i]);
+    }
+
+    return result;
+}
+
+static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
+    hidl_vec<KeyParameter> result;
+    if (set.length == 0 || set.params == nullptr) return result;
+
+    result.resize(set.length);
+    keymaster_key_param_t* params = set.params;
+    for (size_t i = 0; i < set.length; ++i) {
+        auto tag = params[i].tag;
+        result[i].tag = legacy_enum_conversion(tag);
+        switch (typeFromTag(tag)) {
+            case KM_ENUM:
+            case KM_ENUM_REP:
+                result[i].f.integer = params[i].enumerated;
+                break;
+            case KM_UINT:
+            case KM_UINT_REP:
+                result[i].f.integer = params[i].integer;
+                break;
+            case KM_ULONG:
+            case KM_ULONG_REP:
+                result[i].f.longInteger = params[i].long_integer;
+                break;
+            case KM_DATE:
+                result[i].f.dateTime = params[i].date_time;
+                break;
+            case KM_BOOL:
+                result[i].f.boolValue = params[i].boolean;
+                break;
+            case KM_BIGNUM:
+            case KM_BYTES:
+                result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
+                                             params[i].blob.data_length);
+                break;
+            case KM_INVALID:
+            default:
+                params[i].tag = KM_TAG_INVALID;
+                /* just skip */
+                break;
+        }
+    }
+    return result;
+}
+
+void addClientAndAppData(const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                         ::keymaster::AuthorizationSet* params) {
+    params->Clear();
+    if (clientId.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), clientId.size());
+    }
+    if (appData.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+    }
+}
+
+}  // anonymous namespace
+
+TrustyKeymaster4Device::TrustyKeymaster4Device(TrustyKeymaster* impl) : impl_(impl) {}
+
+TrustyKeymaster4Device::~TrustyKeymaster4Device() {}
+
+Return<void> TrustyKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_cb) {
+    _hidl_cb(SecurityLevel::TRUSTED_ENVIRONMENT, "TrustyKeymaster", "Google");
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::getHmacSharingParameters(
+        getHmacSharingParameters_cb _hidl_cb) {
+    const GetHmacSharingParametersResponse response = impl_->GetHmacSharingParameters();
+    // response.params is not the same as the HIDL structure, we need to convert it
+    V4_0::HmacSharingParameters params;
+    params.seed.setToExternal(const_cast<uint8_t*>(response.params.seed.data),
+                              response.params.seed.data_length);
+    static_assert(sizeof(response.params.nonce) == params.nonce.size(), "Nonce sizes don't match");
+    memcpy(params.nonce.data(), response.params.nonce, params.nonce.size());
+    _hidl_cb(legacy_enum_conversion(response.error), params);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::computeSharedHmac(
+        const hidl_vec<HmacSharingParameters>& params, computeSharedHmac_cb _hidl_cb) {
+    ComputeSharedHmacRequest request;
+    request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
+    request.params_array.num_params = params.size();
+    for (size_t i = 0; i < params.size(); ++i) {
+        request.params_array.params_array[i].seed = {params[i].seed.data(), params[i].seed.size()};
+        static_assert(sizeof(request.params_array.params_array[i].nonce) ==
+                              decltype(params[i].nonce)::size(),
+                      "Nonce sizes don't match");
+        memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
+               params[i].nonce.size());
+    }
+
+    auto response = impl_->ComputeSharedHmac(request);
+    hidl_vec<uint8_t> sharing_check;
+    if (response.error == KM_ERROR_OK) {
+        sharing_check = kmBlob2hidlVec(response.sharing_check);
+    }
+
+    _hidl_cb(legacy_enum_conversion(response.error), sharing_check);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::verifyAuthorization(
+        uint64_t challenge, const hidl_vec<KeyParameter>& parametersToVerify,
+        const HardwareAuthToken& authToken, verifyAuthorization_cb _hidl_cb) {
+    VerifyAuthorizationRequest request;
+    request.challenge = challenge;
+    request.parameters_to_verify.Reinitialize(KmParamSet(parametersToVerify));
+    request.auth_token.challenge = authToken.challenge;
+    request.auth_token.user_id = authToken.userId;
+    request.auth_token.authenticator_id = authToken.authenticatorId;
+    request.auth_token.authenticator_type = legacy_enum_conversion(authToken.authenticatorType);
+    request.auth_token.timestamp = authToken.timestamp;
+    KeymasterBlob mac(authToken.mac.data(), authToken.mac.size());
+    request.auth_token.mac = mac;
+
+    auto response = impl_->VerifyAuthorization(request);
+
+    ::android::hardware::keymaster::V4_0::VerificationToken token;
+    token.challenge = response.token.challenge;
+    token.timestamp = response.token.timestamp;
+    token.parametersVerified = kmParamSet2Hidl(response.token.parameters_verified);
+    token.securityLevel = legacy_enum_conversion(response.token.security_level);
+    token.mac = kmBlob2hidlVec(response.token.mac);
+
+    _hidl_cb(legacy_enum_conversion(response.error), token);
+
+    return Void();
+}
+
+Return<ErrorCode> TrustyKeymaster4Device::addRngEntropy(const hidl_vec<uint8_t>& data) {
+    if (data.size() == 0) return ErrorCode::OK;
+    AddEntropyRequest request;
+    request.random_data.Reinitialize(data.data(), data.size());
+
+    AddEntropyResponse response;
+    impl_->AddRngEntropy(request, &response);
+
+    return legacy_enum_conversion(response.error);
+}
+
+Return<void> TrustyKeymaster4Device::generateKey(const hidl_vec<KeyParameter>& keyParams,
+                                                 generateKey_cb _hidl_cb) {
+    GenerateKeyRequest request;
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+
+    GenerateKeyResponse response;
+    impl_->GenerateKey(request, &response);
+
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+    if (response.error == KM_ERROR_OK) {
+        resultKeyBlob = kmBlob2hidlVec(response.key_blob);
+        resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                                           const hidl_vec<uint8_t>& clientId,
+                                                           const hidl_vec<uint8_t>& appData,
+                                                           getKeyCharacteristics_cb _hidl_cb) {
+    GetKeyCharacteristicsRequest request;
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+    addClientAndAppData(clientId, appData, &request.additional_params);
+
+    GetKeyCharacteristicsResponse response;
+    impl_->GetKeyCharacteristics(request, &response);
+
+    KeyCharacteristics resultCharacteristics;
+    if (response.error == KM_ERROR_OK) {
+        resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultCharacteristics);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::importKey(const hidl_vec<KeyParameter>& params,
+                                               KeyFormat keyFormat,
+                                               const hidl_vec<uint8_t>& keyData,
+                                               importKey_cb _hidl_cb) {
+    ImportKeyRequest request;
+    request.key_description.Reinitialize(KmParamSet(params));
+    request.key_format = legacy_enum_conversion(keyFormat);
+    request.SetKeyMaterial(keyData.data(), keyData.size());
+
+    ImportKeyResponse response;
+    impl_->ImportKey(request, &response);
+
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+    if (response.error == KM_ERROR_OK) {
+        resultKeyBlob = kmBlob2hidlVec(response.key_blob);
+        resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::importWrappedKey(
+        const hidl_vec<uint8_t>& wrappedKeyData, const hidl_vec<uint8_t>& wrappingKeyBlob,
+        const hidl_vec<uint8_t>& maskingKey, const hidl_vec<KeyParameter>& unwrappingParams,
+        uint64_t passwordSid, uint64_t biometricSid, importWrappedKey_cb _hidl_cb) {
+    ImportWrappedKeyRequest request;
+    request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+    request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+    request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+    request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+    request.password_sid = passwordSid;
+    request.biometric_sid = biometricSid;
+
+    ImportWrappedKeyResponse response;
+    impl_->ImportWrappedKey(request, &response);
+
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+    if (response.error == KM_ERROR_OK) {
+        resultKeyBlob = kmBlob2hidlVec(response.key_blob);
+        resultCharacteristics.hardwareEnforced = kmParamSet2Hidl(response.enforced);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(response.unenforced);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob, resultCharacteristics);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::exportKey(KeyFormat exportFormat,
+                                               const hidl_vec<uint8_t>& keyBlob,
+                                               const hidl_vec<uint8_t>& clientId,
+                                               const hidl_vec<uint8_t>& appData,
+                                               exportKey_cb _hidl_cb) {
+    ExportKeyRequest request;
+    request.key_format = legacy_enum_conversion(exportFormat);
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+    addClientAndAppData(clientId, appData, &request.additional_params);
+
+    ExportKeyResponse response;
+    impl_->ExportKey(request, &response);
+
+    hidl_vec<uint8_t> resultKeyBlob;
+    if (response.error == KM_ERROR_OK) {
+        resultKeyBlob.setToExternal(response.key_data, response.key_data_length);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultKeyBlob);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                                               const hidl_vec<KeyParameter>& attestParams,
+                                               attestKey_cb _hidl_cb) {
+    AttestKeyRequest request;
+    request.SetKeyMaterial(keyToAttest.data(), keyToAttest.size());
+    request.attest_params.Reinitialize(KmParamSet(attestParams));
+
+    AttestKeyResponse response;
+    impl_->AttestKey(request, &response);
+
+    hidl_vec<hidl_vec<uint8_t>> resultCertChain;
+    if (response.error == KM_ERROR_OK) {
+        resultCertChain = kmCertChain2Hidl(response.certificate_chain);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultCertChain);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                                                const hidl_vec<KeyParameter>& upgradeParams,
+                                                upgradeKey_cb _hidl_cb) {
+    UpgradeKeyRequest request;
+    request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+    request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+    UpgradeKeyResponse response;
+    impl_->UpgradeKey(request, &response);
+
+    if (response.error == KM_ERROR_OK) {
+        _hidl_cb(ErrorCode::OK, kmBlob2hidlVec(response.upgraded_key));
+    } else {
+        _hidl_cb(legacy_enum_conversion(response.error), hidl_vec<uint8_t>());
+    }
+    return Void();
+}
+
+Return<ErrorCode> TrustyKeymaster4Device::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    DeleteKeyRequest request;
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+    DeleteKeyResponse response;
+    impl_->DeleteKey(request, &response);
+
+    return legacy_enum_conversion(response.error);
+}
+
+Return<ErrorCode> TrustyKeymaster4Device::deleteAllKeys() {
+    DeleteAllKeysRequest request;
+    DeleteAllKeysResponse response;
+    impl_->DeleteAllKeys(request, &response);
+
+    return legacy_enum_conversion(response.error);
+}
+
+Return<ErrorCode> TrustyKeymaster4Device::destroyAttestationIds() {
+    return ErrorCode::UNIMPLEMENTED;
+}
+
+Return<void> TrustyKeymaster4Device::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                                           const hidl_vec<KeyParameter>& inParams,
+                                           const HardwareAuthToken& authToken, begin_cb _hidl_cb) {
+    hidl_vec<KeyParameter> extendedParams = injectAuthToken(inParams, authToken);
+    BeginOperationRequest request;
+    request.purpose = legacy_enum_conversion(purpose);
+    request.SetKeyMaterial(key.data(), key.size());
+    request.additional_params.Reinitialize(KmParamSet(extendedParams));
+
+    BeginOperationResponse response;
+    impl_->BeginOperation(request, &response);
+
+    hidl_vec<KeyParameter> resultParams;
+    if (response.error == KM_ERROR_OK) {
+        resultParams = kmParamSet2Hidl(response.output_params);
+    }
+
+    _hidl_cb(legacy_enum_conversion(response.error), resultParams, response.op_handle);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::update(uint64_t operationHandle,
+                                            const hidl_vec<KeyParameter>& inParams,
+                                            const hidl_vec<uint8_t>& input,
+                                            const HardwareAuthToken& authToken,
+                                            const VerificationToken& verificationToken,
+                                            update_cb _hidl_cb) {
+    (void)verificationToken;
+    UpdateOperationRequest request;
+    UpdateOperationResponse response;
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+    hidl_vec<KeyParameter> extendedParams = injectAuthToken(inParams, authToken);
+    uint32_t resultConsumed = 0;
+
+    request.op_handle = operationHandle;
+    request.additional_params.Reinitialize(KmParamSet(extendedParams));
+
+    size_t inp_size = input.size();
+    size_t ser_size = request.SerializedSize();
+
+    if (ser_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
+        response.error = KM_ERROR_INVALID_INPUT_LENGTH;
+    } else {
+        if (ser_size + inp_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
+            inp_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - ser_size;
+        }
+        request.input.Reinitialize(input.data(), inp_size);
+
+        impl_->UpdateOperation(request, &response);
+
+        if (response.error == KM_ERROR_OK) {
+            resultConsumed = response.input_consumed;
+            resultParams = kmParamSet2Hidl(response.output_params);
+            resultBlob = kmBuffer2hidlVec(response.output);
+        }
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultConsumed, resultParams, resultBlob);
+    return Void();
+}
+
+Return<void> TrustyKeymaster4Device::finish(uint64_t operationHandle,
+                                            const hidl_vec<KeyParameter>& inParams,
+                                            const hidl_vec<uint8_t>& input,
+                                            const hidl_vec<uint8_t>& signature,
+                                            const HardwareAuthToken& authToken,
+                                            const VerificationToken& verificationToken,
+                                            finish_cb _hidl_cb) {
+    (void)verificationToken;
+    FinishOperationRequest request;
+    hidl_vec<KeyParameter> extendedParams = injectAuthToken(inParams, authToken);
+    request.op_handle = operationHandle;
+    request.input.Reinitialize(input.data(), input.size());
+    request.signature.Reinitialize(signature.data(), signature.size());
+    request.additional_params.Reinitialize(KmParamSet(extendedParams));
+
+    FinishOperationResponse response;
+    impl_->FinishOperation(request, &response);
+
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+    if (response.error == KM_ERROR_OK) {
+        resultParams = kmParamSet2Hidl(response.output_params);
+        resultBlob = kmBuffer2hidlVec(response.output);
+    }
+    _hidl_cb(legacy_enum_conversion(response.error), resultParams, resultBlob);
+    return Void();
+}
+
+Return<ErrorCode> TrustyKeymaster4Device::abort(uint64_t operationHandle) {
+    AbortOperationRequest request;
+    request.op_handle = operationHandle;
+
+    AbortOperationResponse response;
+    impl_->AbortOperation(request, &response);
+
+    return legacy_enum_conversion(response.error);
+}
+}  // namespace V4_0
+}  // namespace keymaster
diff --git a/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.rc b/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.rc
new file mode 100644
index 0000000..72c9167
--- /dev/null
+++ b/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.rc
@@ -0,0 +1,4 @@
+service vendor.keymaster-4-0 /vendor/bin/hw/android.hardware.keymaster@4.0-service.trusty
+    class early_hal
+    user nobody
+    group drmrpc
diff --git a/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.xml b/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.xml
new file mode 100644
index 0000000..aa30707
--- /dev/null
+++ b/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.keymaster</name>
+        <transport>hwbinder</transport>
+        <version>4.0</version>
+        <interface>
+        <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/trusty/keymaster/4.0/service.cpp b/trusty/keymaster/4.0/service.cpp
new file mode 100644
index 0000000..96eb584
--- /dev/null
+++ b/trusty/keymaster/4.0/service.cpp
@@ -0,0 +1,43 @@
+/*
+**
+** Copyright 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.
+*/
+
+#include <android-base/logging.h>
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <hidl/HidlTransportSupport.h>
+#include <trusty_keymaster/TrustyKeymaster.h>
+#include <trusty_keymaster/TrustyKeymaster4Device.h>
+
+int main() {
+    ::android::hardware::configureRpcThreadpool(1, true);
+    auto trustyKeymaster = new keymaster::TrustyKeymaster();
+    int err = trustyKeymaster->Initialize();
+    if (err != 0) {
+        LOG(FATAL) << "Could not initialize TrustyKeymaster (" << err << ")";
+        return -1;
+    }
+
+    auto keymaster = new ::keymaster::V4_0::TrustyKeymaster4Device(trustyKeymaster);
+
+    auto status = keymaster->registerAsService();
+    if (status != android::OK) {
+        LOG(FATAL) << "Could not register service for Keymaster 4.0 (" << status << ")";
+        return -1;
+    }
+
+    android::hardware::joinRpcThreadpool();
+    return -1;  // Should never get here.
+}
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 819851f..f32a69e 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -101,10 +101,41 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libtrusty",
         "libkeymaster_messages",
         "libkeymaster3device",
         "android.hardware.keymaster@3.0"
     ],
 }
+
+cc_binary {
+    name: "android.hardware.keymaster@4.0-service.trusty",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["4.0/android.hardware.keymaster@4.0-service.trusty.rc"],
+    srcs: [
+        "4.0/service.cpp",
+        "4.0/TrustyKeymaster4Device.cpp",
+        "ipc/trusty_keymaster_ipc.cpp",
+        "TrustyKeymaster.cpp",
+    ],
+
+    local_include_dirs: ["include"],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "libtrusty",
+        "libkeymaster_messages",
+        "libkeymaster4",
+        "android.hardware.keymaster@4.0"
+    ],
+
+    vintf_fragments: ["4.0/android.hardware.keymaster@4.0-service.trusty.xml"],
+}
diff --git a/trusty/keymaster/TrustyKeymaster.cpp b/trusty/keymaster/TrustyKeymaster.cpp
index 7f5e87f..f3ef747 100644
--- a/trusty/keymaster/TrustyKeymaster.cpp
+++ b/trusty/keymaster/TrustyKeymaster.cpp
@@ -172,24 +172,25 @@
     ForwardCommand(KM_ABORT_OPERATION, request, response);
 }
 
-/* Methods for Keymaster 4.0 functionality -- not yet implemented */
 GetHmacSharingParametersResponse TrustyKeymaster::GetHmacSharingParameters() {
+    // Dummy empty buffer to allow ForwardCommand to have something to serialize
+    Buffer request;
     GetHmacSharingParametersResponse response;
-    response.error = KM_ERROR_UNIMPLEMENTED;
+    ForwardCommand(KM_GET_HMAC_SHARING_PARAMETERS, request, &response);
     return response;
 }
 
 ComputeSharedHmacResponse TrustyKeymaster::ComputeSharedHmac(
-        const ComputeSharedHmacRequest& /* request */) {
+        const ComputeSharedHmacRequest& request) {
     ComputeSharedHmacResponse response;
-    response.error = KM_ERROR_UNIMPLEMENTED;
+    ForwardCommand(KM_COMPUTE_SHARED_HMAC, request, &response);
     return response;
 }
 
 VerifyAuthorizationResponse TrustyKeymaster::VerifyAuthorization(
-        const VerifyAuthorizationRequest& /* request */) {
+        const VerifyAuthorizationRequest& request) {
     VerifyAuthorizationResponse response;
-    response.error = KM_ERROR_UNIMPLEMENTED;
+    ForwardCommand(KM_VERIFY_AUTHORIZATION, request, &response);
     return response;
 }
 
diff --git a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster4Device.h b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster4Device.h
new file mode 100644
index 0000000..2be15bc
--- /dev/null
+++ b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster4Device.h
@@ -0,0 +1,105 @@
+/*
+ **
+ ** Copyright 2017, 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 keymaster_V4_0_TrustyKeymaster4Device_H_
+#define keymaster_V4_0_TrustyKeymaster4Device_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+#include <trusty_keymaster/TrustyKeymaster.h>
+
+namespace keymaster {
+
+namespace V4_0 {
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::keymaster::V4_0::ErrorCode;
+using ::android::hardware::keymaster::V4_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
+using ::android::hardware::keymaster::V4_0::HmacSharingParameters;
+using ::android::hardware::keymaster::V4_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V4_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V4_0::KeyFormat;
+using ::android::hardware::keymaster::V4_0::KeyParameter;
+using ::android::hardware::keymaster::V4_0::KeyPurpose;
+using ::android::hardware::keymaster::V4_0::SecurityLevel;
+using ::android::hardware::keymaster::V4_0::Tag;
+using ::android::hardware::keymaster::V4_0::VerificationToken;
+
+class TrustyKeymaster4Device : public IKeymasterDevice {
+  public:
+    explicit TrustyKeymaster4Device(TrustyKeymaster* impl);
+    virtual ~TrustyKeymaster4Device();
+
+    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override;
+    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override;
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+                                   computeSharedHmac_cb) override;
+    Return<void> verifyAuthorization(uint64_t challenge,
+                                     const hidl_vec<KeyParameter>& parametersToVerify,
+                                     const HardwareAuthToken& authToken,
+                                     verifyAuthorization_cb _hidl_cb) override;
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override;
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override;
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+                                  const hidl_vec<uint8_t>& wrappingKeyBlob,
+                                  const hidl_vec<uint8_t>& maskingKey,
+                                  const hidl_vec<KeyParameter>& unwrappingParams,
+                                  uint64_t passwordSid, uint64_t biometricSid,
+                                  importWrappedKey_cb _hidl_cb) override;
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override;
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override;
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override;
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<ErrorCode> deleteAllKeys() override;
+    Return<ErrorCode> destroyAttestationIds() override;
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       begin_cb _hidl_cb) override;
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, update_cb _hidl_cb) override;
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
+    Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+  private:
+    std::unique_ptr<::keymaster::TrustyKeymaster> impl_;
+};
+
+}  // namespace V4_0
+}  // namespace keymaster
+
+#endif  // keymaster_V4_0_TrustyKeymaster4Device_H_
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index c61f7d0..5f56408 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -46,6 +46,8 @@
         return MMC_RPMB;
     } else if (!strcmp(dev_type_name, "virt")) {
         return VIRT_RPMB;
+    } else if (!strcmp(dev_type_name, "sock")) {
+        return SOCK_RPMB;
     } else {
         return UNKNOWN_RPMB;
     }
diff --git a/trusty/storage/proxy/rpmb.c b/trusty/storage/proxy/rpmb.c
index 29827e2..7dfd0d0 100644
--- a/trusty/storage/proxy/rpmb.c
+++ b/trusty/storage/proxy/rpmb.c
@@ -16,11 +16,14 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <scsi/sg.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 #include <unistd.h>
 
 #include <linux/major.h>
@@ -49,6 +52,50 @@
 
 #define MMC_BLOCK_SIZE 512
 
+/*
+ * There should be no timeout for security protocol ioctl call, so we choose a
+ * large number for timeout.
+ * 20000 millisecs == 20 seconds
+ */
+#define TIMEOUT 20000
+
+/*
+ * The sg device driver that supports new interface has a major version number of "3".
+ * SG_GET_VERSION_NUM ioctl() will yield a number greater than or 30000.
+ */
+#define RPMB_MIN_SG_VERSION_NUM 30000
+
+/*
+ * CDB format of SECURITY PROTOCOL IN/OUT commands
+ * (JEDEC Standard No. 220D, Page 264)
+ */
+struct sec_proto_cdb {
+    /*
+     * OPERATION CODE = A2h for SECURITY PROTOCOL IN command,
+     * OPERATION CODE = B5h for SECURITY PROTOCOL OUT command.
+     */
+    uint8_t opcode;
+    /* SECURITY PROTOCOL = ECh (JEDEC Universal Flash Storage) */
+    uint8_t sec_proto;
+    /*
+     * The SECURITY PROTOCOL SPECIFIC field specifies the RPMB Protocol ID.
+     * CDB Byte 2 = 00h and CDB Byte 3 = 01h for RPMB Region 0.
+     */
+    uint8_t cdb_byte_2;
+    uint8_t cdb_byte_3;
+    /*
+     * Byte 4 and 5 are reserved.
+     */
+    uint8_t cdb_byte_4;
+    uint8_t cdb_byte_5;
+    /* ALLOCATION/TRANSFER LENGTH in big-endian */
+    uint32_t length;
+    /* Byte 9 is reserved. */
+    uint8_t cdb_byte_10;
+    /* CONTROL = 00h. */
+    uint8_t ctrl;
+} __packed;
+
 static int rpmb_fd = -1;
 static uint8_t read_buf[4096];
 static enum dev_type dev_type = UNKNOWN_RPMB;
@@ -69,6 +116,21 @@
 
 #endif
 
+static void set_sg_io_hdr(sg_io_hdr_t* io_hdrp, int dxfer_direction, unsigned char cmd_len,
+                          unsigned char mx_sb_len, unsigned int dxfer_len, void* dxferp,
+                          unsigned char* cmdp, void* sbp) {
+    memset(io_hdrp, 0, sizeof(sg_io_hdr_t));
+    io_hdrp->interface_id = 'S';
+    io_hdrp->dxfer_direction = dxfer_direction;
+    io_hdrp->cmd_len = cmd_len;
+    io_hdrp->mx_sb_len = mx_sb_len;
+    io_hdrp->dxfer_len = dxfer_len;
+    io_hdrp->dxferp = dxferp;
+    io_hdrp->cmdp = cmdp;
+    io_hdrp->sbp = sbp;
+    io_hdrp->timeout = TIMEOUT;
+}
+
 static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req) {
     struct {
         struct mmc_ioc_multi_cmd multi;
@@ -130,6 +192,57 @@
     return rc;
 }
 
+static int send_ufs_rpmb_req(int sg_fd, const struct storage_rpmb_send_req* req) {
+    int rc;
+    const uint8_t* write_buf = req->payload;
+    /*
+     * Meaning of member values are stated on the definition of struct sec_proto_cdb.
+     */
+    struct sec_proto_cdb in_cdb = {0xA2, 0xEC, 0x00, 0x01, 0x00, 0x00, 0, 0x00, 0x00};
+    struct sec_proto_cdb out_cdb = {0xB5, 0xEC, 0x00, 0x01, 0x00, 0x00, 0, 0x00, 0x00};
+    unsigned char sense_buffer[32];
+
+    if (req->reliable_write_size) {
+        /* Prepare SECURITY PROTOCOL OUT command. */
+        out_cdb.length = __builtin_bswap32(req->reliable_write_size);
+        sg_io_hdr_t io_hdr;
+        set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
+                      req->reliable_write_size, (void*)write_buf, (unsigned char*)&out_cdb,
+                      sense_buffer);
+        rc = ioctl(sg_fd, SG_IO, &io_hdr);
+        if (rc < 0) {
+            ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
+        }
+        write_buf += req->reliable_write_size;
+    }
+
+    if (req->write_size) {
+        /* Prepare SECURITY PROTOCOL OUT command. */
+        out_cdb.length = __builtin_bswap32(req->write_size);
+        sg_io_hdr_t io_hdr;
+        set_sg_io_hdr(&io_hdr, SG_DXFER_TO_DEV, sizeof(out_cdb), sizeof(sense_buffer),
+                      req->write_size, (void*)write_buf, (unsigned char*)&out_cdb, sense_buffer);
+        rc = ioctl(sg_fd, SG_IO, &io_hdr);
+        if (rc < 0) {
+            ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
+        }
+        write_buf += req->write_size;
+    }
+
+    if (req->read_size) {
+        /* Prepare SECURITY PROTOCOL IN command. */
+        out_cdb.length = __builtin_bswap32(req->read_size);
+        sg_io_hdr_t io_hdr;
+        set_sg_io_hdr(&io_hdr, SG_DXFER_FROM_DEV, sizeof(in_cdb), sizeof(sense_buffer),
+                      req->read_size, read_buf, (unsigned char*)&in_cdb, sense_buffer);
+        rc = ioctl(sg_fd, SG_IO, &io_hdr);
+        if (rc < 0) {
+            ALOGE("%s: ufs ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
+        }
+    }
+    return rc;
+}
+
 static int send_virt_rpmb_req(int rpmb_fd, void* read_buf, size_t read_size, const void* payload,
                               size_t payload_size) {
     int rc;
@@ -192,7 +305,14 @@
             msg->result = STORAGE_ERR_GENERIC;
             goto err_response;
         }
-    } else if (dev_type == VIRT_RPMB) {
+    } else if (dev_type == UFS_RPMB) {
+        rc = send_ufs_rpmb_req(rpmb_fd, req);
+        if (rc < 0) {
+            ALOGE("send_ufs_rpmb_req failed: %d, %s\n", rc, strerror(errno));
+            msg->result = STORAGE_ERR_GENERIC;
+            goto err_response;
+        }
+    } else if ((dev_type == VIRT_RPMB) || (dev_type == SOCK_RPMB)) {
         size_t payload_size = req->reliable_write_size + req->write_size;
         rc = send_virt_rpmb_req(rpmb_fd, read_buf, req->read_size, req->payload, payload_size);
         if (rc < 0) {
@@ -231,15 +351,46 @@
 }
 
 int rpmb_open(const char* rpmb_devname, enum dev_type open_dev_type) {
-    int rc;
+    int rc, sg_version_num;
     dev_type = open_dev_type;
 
-    rc = open(rpmb_devname, O_RDWR, 0);
-    if (rc < 0) {
-        ALOGE("unable (%d) to open rpmb device '%s': %s\n", errno, rpmb_devname, strerror(errno));
-        return rc;
+    if (dev_type != SOCK_RPMB) {
+        rc = open(rpmb_devname, O_RDWR, 0);
+        if (rc < 0) {
+            ALOGE("unable (%d) to open rpmb device '%s': %s\n", errno, rpmb_devname, strerror(errno));
+            return rc;
+        }
+        rpmb_fd = rc;
+
+        /* For UFS, it is prudent to check we have a sg device by calling an ioctl */
+        if (dev_type == UFS_RPMB) {
+            if ((ioctl(rpmb_fd, SG_GET_VERSION_NUM, &sg_version_num) < 0) ||
+                (sg_version_num < RPMB_MIN_SG_VERSION_NUM)) {
+                ALOGE("%s is not a sg device, or old sg driver\n", rpmb_devname);
+                return -1;
+            }
+        }
+    } else {
+        struct sockaddr_un unaddr;
+        struct sockaddr *addr = (struct sockaddr *)&unaddr;
+        rc = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (rc < 0) {
+            ALOGE("unable (%d) to create socket: %s\n", errno, strerror(errno));
+            return rc;
+        }
+        rpmb_fd = rc;
+
+        memset(&unaddr, 0, sizeof(unaddr));
+        unaddr.sun_family = AF_UNIX;
+        // TODO if it overflowed, bail rather than connecting?
+        strncpy(unaddr.sun_path, rpmb_devname, sizeof(unaddr.sun_path)-1);
+        rc = connect(rpmb_fd, addr, sizeof(unaddr));
+        if (rc < 0) {
+            ALOGE("unable (%d) to connect to rpmb socket '%s': %s\n", errno, rpmb_devname, strerror(errno));
+            return rc;
+        }
     }
-    rpmb_fd = rc;
+
     return 0;
 }
 
diff --git a/trusty/storage/proxy/rpmb.h b/trusty/storage/proxy/rpmb.h
index 4c330c9..f4e1b51 100644
--- a/trusty/storage/proxy/rpmb.h
+++ b/trusty/storage/proxy/rpmb.h
@@ -18,7 +18,7 @@
 #include <stdint.h>
 #include <trusty/interface/storage.h>
 
-enum dev_type { UNKNOWN_RPMB, MMC_RPMB, VIRT_RPMB };
+enum dev_type { UNKNOWN_RPMB, MMC_RPMB, VIRT_RPMB, UFS_RPMB, SOCK_RPMB };
 
 int rpmb_open(const char* rpmb_devname, enum dev_type dev_type);
 int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len);
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 0a0ecec..fd8daa8 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -19,9 +19,12 @@
 # to pull in the baseline set of Trusty specific modules.
 #
 
+# For gatekeeper, we include the generic -service and -impl to use legacy
+# HAL loading of gatekeeper.trusty.
+
 PRODUCT_PACKAGES += \
-	android.hardware.keymaster@3.0-service.trusty \
-	gatekeeper.trusty
+	android.hardware.keymaster@4.0-service.trusty \
+	android.hardware.gatekeeper@1.0-service.trusty
 
 PRODUCT_PROPERTY_OVERRIDES += \
 	ro.hardware.keystore=trusty \
diff --git a/libmeminfo/libdmabufinfo/tools/Android.bp b/trusty/utils/rpmb_dev/Android.bp
similarity index 74%
rename from libmeminfo/libdmabufinfo/tools/Android.bp
rename to trusty/utils/rpmb_dev/Android.bp
index 224b68e..e923e82 100644
--- a/libmeminfo/libdmabufinfo/tools/Android.bp
+++ b/trusty/utils/rpmb_dev/Android.bp
@@ -2,8 +2,7 @@
 //
 // 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
-//
+// 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
@@ -13,18 +12,22 @@
 // limitations under the License.
 
 cc_binary {
-    name: "dmabuf_dump",
+    name: "rpmb_dev",
+    vendor: true,
+
+    srcs: [
+        "rpmb_dev.c",
+    ],
+    shared_libs: [
+        "libc",
+        "liblog",
+        "libcrypto",
+    ],
     cflags: [
         "-Wall",
         "-Werror",
     ],
-
-    srcs: ["dmabuf_dump.cpp"],
-    shared_libs: [
-        "libbase",
+    init_rc: [
+        "rpmb_dev.rc",
     ],
-    static_libs: [
-        "libdmabufinfo",
-    ],
-    product_specific: true,
-}
\ No newline at end of file
+}
diff --git a/trusty/utils/rpmb_dev/rpmb.h b/trusty/utils/rpmb_dev/rpmb.h
new file mode 100644
index 0000000..ab7e8d8
--- /dev/null
+++ b/trusty/utils/rpmb_dev/rpmb.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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 __RPMB_H__
+#define __RPMB_H__
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+struct rpmb_key {
+    uint8_t byte[32];
+};
+
+struct rpmb_state;
+
+#define RPMB_BUF_SIZE 256
+
+/* provides */
+int rpmb_init(struct rpmb_state** statep,
+              void* mmc_handle,
+              const struct rpmb_key* key);
+void rpmb_uninit(struct rpmb_state* statep);
+int rpmb_read(struct rpmb_state* state,
+              void* buf,
+              uint16_t addr,
+              uint16_t count);
+/* count must be 1 or 2, addr must be aligned */
+int rpmb_write(struct rpmb_state* state,
+               const void* buf,
+               uint16_t addr,
+               uint16_t count,
+               bool sync);
+
+/* needs */
+int rpmb_send(void* mmc_handle,
+              void* reliable_write_buf,
+              size_t reliable_write_size,
+              void* write_buf,
+              size_t write_buf_size,
+              void* read_buf,
+              size_t read_buf_size,
+              bool sync);
+
+#endif
diff --git a/trusty/utils/rpmb_dev/rpmb_dev.c b/trusty/utils/rpmb_dev/rpmb_dev.c
new file mode 100644
index 0000000..af97eba
--- /dev/null
+++ b/trusty/utils/rpmb_dev/rpmb_dev.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define LOG_TAG "rpmb_mock"
+
+#include "rpmb_protocol.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <log/log.h>
+#include <openssl/hmac.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+/* verbose is an int for getopt */
+static int verbose = false;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+HMAC_CTX* HMAC_CTX_new(void) {
+    HMAC_CTX* ctx = malloc(sizeof(*ctx));
+    if (ctx != NULL) {
+        HMAC_CTX_init(ctx);
+    }
+    return ctx;
+}
+
+void HMAC_CTX_free(HMAC_CTX* ctx) {
+    if (ctx != NULL) {
+        HMAC_CTX_cleanup(ctx);
+        free(ctx);
+    }
+}
+
+#endif
+
+#define MAX_WRITE_COUNTER (0xffffffff)
+
+struct rpmb_data_header {
+    uint32_t write_counter;
+    uint16_t max_block;
+    uint8_t pad1;
+    uint8_t key_programmed;
+    struct rpmb_key key;
+    uint8_t pad[512 - 4 - 2 - 1 - 1 - sizeof(struct rpmb_key)];
+};
+
+#define MAX_PACKET_COUNT (8)
+
+struct rpmb_dev_state {
+    struct rpmb_data_header header;
+    struct rpmb_packet cmd[MAX_PACKET_COUNT];
+    struct rpmb_packet res[MAX_PACKET_COUNT];
+    uint16_t cmd_count;
+    uint16_t res_count;
+    int data_fd;
+};
+
+/* TODO: move to common location */
+static int rpmb_mac(struct rpmb_key key, struct rpmb_packet* packet, size_t packet_count,
+                    struct rpmb_key* mac) {
+    size_t i;
+    int hmac_ret;
+    unsigned int md_len;
+    HMAC_CTX* hmac_ctx;
+
+    hmac_ctx = HMAC_CTX_new();
+    hmac_ret = HMAC_Init_ex(hmac_ctx, &key, sizeof(key), EVP_sha256(), NULL);
+    if (!hmac_ret) {
+        ALOGE("HMAC_Init_ex failed\n");
+        goto err;
+    }
+    for (i = 0; i < packet_count; i++) {
+        hmac_ret = HMAC_Update(hmac_ctx, packet[i].data, 284);
+        if (!hmac_ret) {
+            ALOGE("HMAC_Update failed\n");
+            goto err;
+        }
+    }
+    hmac_ret = HMAC_Final(hmac_ctx, mac->byte, &md_len);
+    if (md_len != sizeof(mac->byte)) {
+        ALOGE("bad md_len %d != %zd\n", md_len, sizeof(mac->byte));
+        exit(1);
+    }
+    if (!hmac_ret) {
+        ALOGE("HMAC_Final failed\n");
+        goto err;
+    }
+
+err:
+    HMAC_CTX_free(hmac_ctx);
+    return hmac_ret ? 0 : -1;
+}
+
+static int rpmb_file_seek(struct rpmb_dev_state* s, uint16_t addr) {
+    int ret;
+    int pos = addr * RPMB_PACKET_DATA_SIZE + sizeof(s->header);
+    ret = lseek(s->data_fd, pos, SEEK_SET);
+    if (ret != pos) {
+        ALOGE("rpmb_dev: seek to %d failed, got %d\n", pos, ret);
+        return -1;
+    }
+    return 0;
+}
+
+static uint16_t rpmb_dev_program_key(struct rpmb_dev_state* s) {
+    int ret;
+
+    if (s->header.key_programmed) {
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    s->header.key = s->cmd[0].key_mac;
+    s->header.key_programmed = 1;
+
+    ret = lseek(s->data_fd, 0, SEEK_SET);
+    if (ret) {
+        ALOGE("rpmb_dev: Failed to seek rpmb data file\n");
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    ret = write(s->data_fd, &s->header, sizeof(s->header));
+    if (ret != sizeof(s->header)) {
+        ALOGE("rpmb_dev: Failed to write rpmb key: %d, %s\n", ret, strerror(errno));
+
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    return RPMB_RES_OK;
+}
+
+static uint16_t rpmb_dev_get_counter(struct rpmb_dev_state* s) {
+    s->res[0].write_counter = rpmb_u32(s->header.write_counter);
+
+    return RPMB_RES_OK;
+}
+
+static uint16_t rpmb_dev_data_write(struct rpmb_dev_state* s) {
+    uint16_t addr = rpmb_get_u16(s->cmd[0].address);
+    uint16_t block_count = s->cmd_count;
+    uint32_t write_counter;
+    int ret;
+
+    if (s->header.write_counter == MAX_WRITE_COUNTER) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Write counter expired\n");
+        }
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    write_counter = rpmb_get_u32(s->cmd[0].write_counter);
+    if (s->header.write_counter != write_counter) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Invalid write counter %u. Expected: %u\n", write_counter,
+                  s->header.write_counter);
+        }
+        return RPMB_RES_COUNT_FAILURE;
+    }
+
+    ret = rpmb_file_seek(s, addr);
+    if (ret) {
+        ALOGE("rpmb_dev: Failed to seek rpmb data file\n");
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    for (int i = 0; i < block_count; i++) {
+        ret = write(s->data_fd, s->cmd[i].data, RPMB_PACKET_DATA_SIZE);
+        if (ret != RPMB_PACKET_DATA_SIZE) {
+            ALOGE("rpmb_dev: Failed to write rpmb data file: %d, %s\n", ret, strerror(errno));
+            return RPMB_RES_WRITE_FAILURE;
+        }
+    }
+
+    s->header.write_counter++;
+
+    ret = lseek(s->data_fd, 0, SEEK_SET);
+    if (ret) {
+        ALOGE("rpmb_dev: Failed to seek rpmb data file\n");
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    ret = write(s->data_fd, &s->header.write_counter, sizeof(s->header.write_counter));
+    if (ret != sizeof(s->header.write_counter)) {
+        ALOGE("rpmb_dev: Failed to write rpmb write counter: %d, %s\n", ret, strerror(errno));
+
+        return RPMB_RES_WRITE_FAILURE;
+    }
+
+    s->res[0].write_counter = rpmb_u32(s->header.write_counter);
+    return RPMB_RES_OK;
+}
+
+static uint16_t rpmb_dev_data_read(struct rpmb_dev_state* s) {
+    uint16_t addr;
+    uint16_t block_count;
+    int ret;
+
+    addr = rpmb_get_u16(s->cmd[0].address);
+    block_count = s->res_count;
+
+    rpmb_file_seek(s, addr);
+
+    for (int i = 0; i < block_count; i++) {
+        ret = read(s->data_fd, s->res[i].data, RPMB_PACKET_DATA_SIZE);
+        if (ret != 0 && ret != RPMB_PACKET_DATA_SIZE) {
+            ALOGE("rpmb_dev: Failed to read rpmb data file: %d, %s\n", ret, strerror(errno));
+            return RPMB_RES_READ_FAILURE;
+        }
+    }
+
+    return RPMB_RES_OK;
+}
+
+struct rpmb_dev_cmd {
+    uint16_t (*func)(struct rpmb_dev_state* s);
+    uint16_t resp;
+    bool key_mac_is_key;
+    bool check_mac;
+    bool check_result_read;
+    bool check_key_programmed;
+    bool check_addr;
+    bool multi_packet_cmd;
+    bool multi_packet_res;
+    bool res_mac;
+};
+
+static struct rpmb_dev_cmd rpmb_dev_cmd_table[] = {
+        [RPMB_REQ_PROGRAM_KEY] =
+                {
+                        .func = rpmb_dev_program_key,
+                        .resp = RPMB_RESP_PROGRAM_KEY,
+                        .key_mac_is_key = true,
+                        .check_result_read = true,
+                },
+        [RPMB_REQ_GET_COUNTER] =
+                {
+                        .func = rpmb_dev_get_counter,
+                        .resp = RPMB_RESP_GET_COUNTER,
+                        .check_key_programmed = true,
+                        .res_mac = true,
+                },
+        [RPMB_REQ_DATA_WRITE] =
+                {
+                        .func = rpmb_dev_data_write,
+                        .resp = RPMB_RESP_DATA_WRITE,
+                        .check_mac = true,
+                        .check_result_read = true,
+                        .check_key_programmed = true,
+                        .check_addr = true,
+                        .multi_packet_cmd = true,
+                        .res_mac = true,
+                },
+        [RPMB_REQ_DATA_READ] =
+                {
+                        .func = rpmb_dev_data_read,
+                        .resp = RPMB_RESP_DATA_READ,
+                        .check_addr = true,
+                        .multi_packet_res = true,
+                        .res_mac = true,
+                },
+};
+
+#define countof(arr) (sizeof(arr) / sizeof(arr[0]))
+
+static void rpmb_dev_process_cmd(struct rpmb_dev_state* s) {
+    assert(s->cmd_count > 0);
+    assert(s->res_count > 0);
+    uint16_t req_resp = rpmb_get_u16(s->cmd[0].req_resp);
+    uint16_t addr = rpmb_get_u16(s->cmd[0].address);
+    uint16_t sub_req;
+    uint16_t cmd_index = req_resp < countof(rpmb_dev_cmd_table) ? req_resp : 0;
+    struct rpmb_dev_cmd* cmd = &rpmb_dev_cmd_table[cmd_index];
+    uint16_t result = RPMB_RES_GENERAL_FAILURE;
+    struct rpmb_key mac;
+    uint16_t block_count = 0;
+
+    if (cmd->check_result_read) {
+        sub_req = rpmb_get_u16(s->cmd[s->cmd_count - 1].req_resp);
+        if (sub_req != RPMB_REQ_RESULT_READ) {
+            if (verbose) {
+                ALOGE("rpmb_dev: Request %d, missing result read request, got %d, cmd_count %d\n",
+                      req_resp, sub_req, s->cmd_count);
+            }
+            goto err;
+        }
+        assert(s->cmd_count > 1);
+        s->cmd_count--;
+    }
+
+    if (cmd->check_mac) {
+        if (rpmb_mac(s->header.key, s->cmd, s->cmd_count, &mac) != 0) {
+            ALOGE("rpmb_dev: failed to caclulate mac\n");
+            goto err;
+        }
+    } else if (cmd->key_mac_is_key) {
+        mac = s->cmd[s->cmd_count - 1].key_mac;
+    } else {
+        memset(mac.byte, 0, sizeof(mac.byte));
+    }
+
+    if (memcmp(&mac, s->cmd[s->cmd_count - 1].key_mac.byte, sizeof(mac))) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Request %d, invalid MAC, cmd_count %d\n", req_resp, s->cmd_count);
+        }
+        if (cmd->check_mac) {
+            result = RPMB_RES_AUTH_FAILURE;
+        }
+        goto err;
+    }
+
+    if (cmd->multi_packet_cmd) {
+        block_count = s->cmd_count;
+    }
+    if (cmd->multi_packet_res) {
+        block_count = s->res_count;
+    }
+
+    if (cmd->check_addr && (addr + block_count > s->header.max_block + 1)) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Request %d, invalid addr: 0x%x count 0x%x, Out of bounds. Max addr "
+                  "0x%x\n",
+                  req_resp, addr, block_count, s->header.max_block + 1);
+        }
+        result = RPMB_RES_ADDR_FAILURE;
+        goto err;
+    }
+    if (!cmd->check_addr && addr) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Request %d, invalid addr: 0x%x != 0\n", req_resp, addr);
+        }
+        goto err;
+    }
+
+    for (int i = 1; i < s->cmd_count; i++) {
+        sub_req = rpmb_get_u16(s->cmd[i].req_resp);
+        if (sub_req != req_resp) {
+            if (verbose) {
+                ALOGE("rpmb_dev: Request %d, sub-request mismatch, %d, at %d\n", req_resp, i,
+                      sub_req);
+            }
+            goto err;
+        }
+    }
+    if (!cmd->multi_packet_cmd && s->cmd_count != 1) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Request %d, bad cmd count %d, expected 1\n", req_resp, s->cmd_count);
+        }
+        goto err;
+    }
+    if (!cmd->multi_packet_res && s->res_count != 1) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Request %d, bad res count %d, expected 1\n", req_resp, s->res_count);
+        }
+        goto err;
+    }
+
+    if (cmd->check_key_programmed && !s->header.key_programmed) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Request %d, key is not programmed\n", req_resp);
+        }
+        s->res[0].result = rpmb_u16(RPMB_RES_NO_AUTH_KEY);
+        return;
+    }
+
+    if (!cmd->func) {
+        if (verbose) {
+            ALOGE("rpmb_dev: Unsupported request: %d\n", req_resp);
+        }
+        goto err;
+    }
+
+    result = cmd->func(s);
+
+err:
+    if (s->header.write_counter == MAX_WRITE_COUNTER) {
+        result |= RPMB_RES_WRITE_COUNTER_EXPIRED;
+    }
+
+    for (int i = 0; i < s->res_count; i++) {
+        s->res[i].nonce = s->cmd[0].nonce;
+        s->res[i].address = rpmb_u16(addr);
+        s->res[i].block_count = rpmb_u16(block_count);
+        s->res[i].result = rpmb_u16(result);
+        s->res[i].req_resp = rpmb_u16(cmd->resp);
+    }
+    if (cmd->res_mac) {
+        rpmb_mac(s->header.key, s->res, s->res_count, &s->res[s->res_count - 1].key_mac);
+    }
+}
+
+/*
+ * Receives data until one of the following is true:
+ * - The buffer is full (return will be len)
+ * - The connection closed (return > 0, < len)
+ * - An error occurred (return will be the negative error code from recv)
+ */
+ssize_t recv_until(int sock, void* dest_in, size_t len) {
+    size_t bytes_recvd = 0;
+    char* dest = dest_in;
+    while (bytes_recvd < len) {
+        ssize_t ret = recv(sock, dest, len - bytes_recvd, 0);
+        if (ret < 0) {
+            return ret;
+        }
+        dest += ret;
+        bytes_recvd += ret;
+        if (ret == 0) {
+            break;
+        }
+    }
+    return bytes_recvd;
+}
+
+/*
+ * Handles an incoming connection to the rpmb daemon.
+ * Returns 0 if the client disconnects without violating the protocol.
+ * Returns a negative value if we terminated the connection abnormally.
+ *
+ * Arguments:
+ *   conn_sock - an fd to send/recv on
+ *   s - an initialized rpmb device
+ */
+int handle_conn(struct rpmb_dev_state* s, int conn_sock) {
+    int ret;
+
+    while (true) {
+        memset(s->res, 0, sizeof(s->res));
+        ret = recv_until(conn_sock, &s->res_count, sizeof(s->res_count));
+
+        /*
+         * Disconnected while not in the middle of anything.
+         */
+        if (ret <= 0) {
+            return 0;
+        }
+
+        if (s->res_count > MAX_PACKET_COUNT) {
+            ALOGE("rpmb_dev: Receive count too large: %d\n", s->res_count);
+            return -1;
+        }
+        if (s->res_count <= 0) {
+            ALOGE("rpmb_dev: Receive count too small: %d\n", s->res_count);
+            return -1;
+        }
+
+        ret = recv_until(conn_sock, &s->cmd_count, sizeof(s->cmd_count));
+        if (ret != sizeof(s->cmd_count)) {
+            ALOGE("rpmb_dev: Failed to read cmd_count");
+            return -1;
+        }
+
+        if (s->cmd_count == 0) {
+            ALOGE("rpmb_dev: Must contain at least one command\n");
+            return -1;
+        }
+
+        if (s->cmd_count > MAX_PACKET_COUNT) {
+            ALOGE("rpmb_dev: Command count is too large\n");
+            return -1;
+        }
+
+        size_t cmd_size = s->cmd_count * sizeof(s->cmd[0]);
+        ret = recv_until(conn_sock, s->cmd, cmd_size);
+        if (ret != (int)cmd_size) {
+            ALOGE("rpmb_dev: Failed to read command: "
+                  "cmd_size: %zu ret: %d, %s\n",
+                  cmd_size, ret, strerror(errno));
+            return -1;
+        }
+
+        rpmb_dev_process_cmd(s);
+
+        size_t resp_size = sizeof(s->res[0]) * s->res_count;
+        ret = send(conn_sock, s->res, resp_size, 0);
+        if (ret != (int)resp_size) {
+            ALOGE("rpmb_dev: Failed to send response: %d, %s\n", ret, strerror(errno));
+            return -1;
+        }
+    }
+}
+
+void usage(const char* argv0) {
+    fprintf(stderr, "Usage: %s [-d|--dev] <datafile> [--sock] <socket_path>\n", argv0);
+    fprintf(stderr, "or:    %s [-d|--dev] <datafile> [--size <size>] [--key key]\n", argv0);
+}
+
+int main(int argc, char** argv) {
+    struct rpmb_dev_state s;
+    int ret;
+    int cmdres_sock;
+    struct sockaddr_un cmdres_sockaddr;
+    const char* data_file_name = NULL;
+    const char* socket_path = NULL;
+    int open_flags;
+    int init = false;
+
+    struct option long_options[] = {{"size", required_argument, 0, 0},
+                                    {"key", required_argument, 0, 0},
+                                    {"sock", required_argument, 0, 0},
+                                    {"dev", required_argument, 0, 'd'},
+                                    {"init", no_argument, &init, true},
+                                    {"verbose", no_argument, &verbose, true},
+                                    {0, 0, 0, 0}};
+
+    memset(&s.header, 0, sizeof(s.header));
+
+    while (1) {
+        int c;
+        int option_index = 0;
+        c = getopt_long(argc, argv, "d:", long_options, &option_index);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+            /* long args */
+            case 0:
+                switch (option_index) {
+                    /* size */
+                    case 0:
+                        s.header.max_block = atoi(optarg) - 1;
+                        break;
+                    /* key */
+                    case 1:
+                        for (size_t i = 0; i < sizeof(s.header.key.byte); i++) {
+                            if (!optarg) {
+                                break;
+                            }
+                            s.header.key.byte[i] = strtol(optarg, &optarg, 16);
+                            s.header.key_programmed = 1;
+                        }
+                        break;
+                    /* sock */
+                    case 2:
+                        socket_path = optarg;
+                        break;
+                }
+                break;
+            /* dev */
+            case 'd':
+                data_file_name = optarg;
+                break;
+            default:
+                usage(argv[0]);
+                return EXIT_FAILURE;
+        }
+    }
+
+    /*
+     * We always need a data file, and at exactly one of --init or --sock
+     * must be specified.
+     */
+    if (!data_file_name || (!init == !socket_path)) {
+        usage(argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    /*
+     * If the file is already initialized, exit early.
+     */
+    if (init && !access(data_file_name, F_OK)) {
+        return EXIT_SUCCESS;
+    }
+
+    open_flags = O_RDWR;
+    if (init) {
+        open_flags |= O_CREAT | O_TRUNC;
+    }
+    s.data_fd = open(data_file_name, open_flags, S_IWUSR | S_IRUSR);
+    if (s.data_fd < 0) {
+        ALOGE("rpmb_dev: Failed to open rpmb data file, %s: %s\n", data_file_name, strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    if (init) {
+        /* Create new rpmb data file */
+        if (s.header.max_block == 0) {
+            s.header.max_block = 512 - 1;
+        }
+        ret = write(s.data_fd, &s.header, sizeof(s.header));
+        if (ret != sizeof(s.header)) {
+            ALOGE("rpmb_dev: Failed to write rpmb data file: %d, %s\n", ret, strerror(errno));
+            return EXIT_FAILURE;
+        }
+        return EXIT_SUCCESS;
+    }
+
+    ret = read(s.data_fd, &s.header, sizeof(s.header));
+    if (ret != sizeof(s.header)) {
+        ALOGE("rpmb_dev: Failed to read rpmb data file: %d, %s\n", ret, strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    cmdres_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (cmdres_sock < 0) {
+        ALOGE("rpmb_dev: Failed to create command/response socket: %s\n", strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    cmdres_sockaddr.sun_family = AF_UNIX;
+    strncpy(cmdres_sockaddr.sun_path, socket_path, sizeof(cmdres_sockaddr.sun_path));
+
+    ret = bind(cmdres_sock, (struct sockaddr*)&cmdres_sockaddr, sizeof(struct sockaddr_un));
+    if (ret < 0) {
+        ALOGE("rpmb_dev: Failed to bind command/response socket: %s: %s\n", socket_path,
+              strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    ret = listen(cmdres_sock, 1);
+    if (ret < 0) {
+        ALOGE("rpmb_dev: Failed to listen on command/response socket: %s\n", strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    while (true) {
+        int conn_sock = accept(cmdres_sock, NULL, NULL);
+        if (conn_sock < 0) {
+            ALOGE("rpmb_dev: Could not accept connection: %s\n", strerror(errno));
+            return EXIT_FAILURE;
+        }
+        ret = handle_conn(&s, conn_sock);
+        close(conn_sock);
+        if (ret) {
+            ALOGE("rpmb_dev: Connection terminated: %d", ret);
+        }
+    }
+}
diff --git a/trusty/utils/rpmb_dev/rpmb_dev.rc b/trusty/utils/rpmb_dev/rpmb_dev.rc
new file mode 100644
index 0000000..9f60e81
--- /dev/null
+++ b/trusty/utils/rpmb_dev/rpmb_dev.rc
@@ -0,0 +1,29 @@
+# RPMB Mock
+on post-fs-data
+    mkdir /data/vendor/ss
+    chown root system /data/vendor/ss
+    chmod 0770 /data/vendor/ss
+    rm /data/vendor/ss/rpmb_sock
+    start rpmb_mock_init
+    start rpmb_mock
+
+    # Storage proxy
+    start storageproxyd
+
+service storageproxyd /vendor/bin/storageproxyd -d /dev/trusty-ipc-dev0 \
+        -r /data/vendor/ss/rpmb_sock -p /data/vendor/ss -t sock
+    class main
+    disabled
+    user root
+
+service rpmb_mock_init /vendor/bin/rpmb_dev --dev /data/vendor/ss/RPMB_DATA --init --key "ea df 64 44 ea 65 5d 1c 87 27 d4 20 71 0d 53 42 dd 73 a3 38 63 e1 d7 94 c3 72 a6 ea e0 64 64 e6" --size 2048
+    disabled
+    user system
+    group system
+    oneshot
+
+service rpmb_mock /vendor/bin/rpmb_dev --dev /data/vendor/ss/RPMB_DATA --sock /data/vendor/ss/rpmb_sock
+    class main
+    disabled
+    user system
+    group system
diff --git a/trusty/utils/rpmb_dev/rpmb_protocol.h b/trusty/utils/rpmb_dev/rpmb_protocol.h
new file mode 100644
index 0000000..bfcb806
--- /dev/null
+++ b/trusty/utils/rpmb_dev/rpmb_protocol.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include "rpmb.h" /* For struct rpmb_key */
+
+#define MMC_READ_MULTIPLE_BLOCK 18
+#define MMC_WRITE_MULTIPLE_BLOCK 25
+#define MMC_RELIABLE_WRITE_FLAG (1 << 31)
+
+#define MMC_RSP_PRESENT (1 << 0)
+#define MMC_RSP_CRC (1 << 2)
+#define MMC_RSP_OPCODE (1 << 4)
+#define MMC_CMD_ADTC (1 << 5)
+#define MMC_RSP_SPI_S1 (1 << 7)
+#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1)
+
+struct rpmb_nonce {
+    uint8_t byte[16];
+};
+
+struct rpmb_u16 {
+    uint8_t byte[2];
+};
+
+struct rpmb_u32 {
+    uint8_t byte[4];
+};
+
+#define RPMB_PACKET_DATA_SIZE (256)
+
+struct rpmb_packet {
+    uint8_t pad[196];
+    struct rpmb_key key_mac;
+    uint8_t data[RPMB_PACKET_DATA_SIZE];
+    struct rpmb_nonce nonce;
+    struct rpmb_u32 write_counter;
+    struct rpmb_u16 address;
+    struct rpmb_u16 block_count;
+    struct rpmb_u16 result;
+    struct rpmb_u16 req_resp;
+};
+
+enum rpmb_request {
+    RPMB_REQ_PROGRAM_KEY = 0x0001,
+    RPMB_REQ_GET_COUNTER = 0x0002,
+    RPMB_REQ_DATA_WRITE = 0x0003,
+    RPMB_REQ_DATA_READ = 0x0004,
+    RPMB_REQ_RESULT_READ = 0x0005,
+};
+
+enum rpmb_response {
+    RPMB_RESP_PROGRAM_KEY = 0x0100,
+    RPMB_RESP_GET_COUNTER = 0x0200,
+    RPMB_RESP_DATA_WRITE = 0x0300,
+    RPMB_RESP_DATA_READ = 0x0400,
+};
+
+enum rpmb_result {
+    RPMB_RES_OK = 0x0000,
+    RPMB_RES_GENERAL_FAILURE = 0x0001,
+    RPMB_RES_AUTH_FAILURE = 0x0002,
+    RPMB_RES_COUNT_FAILURE = 0x0003,
+    RPMB_RES_ADDR_FAILURE = 0x0004,
+    RPMB_RES_WRITE_FAILURE = 0x0005,
+    RPMB_RES_READ_FAILURE = 0x0006,
+    RPMB_RES_NO_AUTH_KEY = 0x0007,
+
+    RPMB_RES_WRITE_COUNTER_EXPIRED = 0x0080,
+};
+
+static inline struct rpmb_u16 rpmb_u16(uint16_t val) {
+    struct rpmb_u16 ret = {{
+            (uint8_t)(val >> 8),
+            (uint8_t)(val >> 0),
+    }};
+    return ret;
+}
+
+static inline struct rpmb_u32 rpmb_u32(uint32_t val) {
+    struct rpmb_u32 ret = {{
+            (uint8_t)(val >> 24),
+            (uint8_t)(val >> 16),
+            (uint8_t)(val >> 8),
+            (uint8_t)(val >> 0),
+    }};
+    return ret;
+}
+
+static inline uint16_t rpmb_get_u16(struct rpmb_u16 u16) {
+    size_t i;
+    uint16_t val;
+
+    val = 0;
+    for (i = 0; i < sizeof(u16.byte); i++)
+        val = val << 8 | u16.byte[i];
+
+    return val;
+}
+
+static inline uint32_t rpmb_get_u32(struct rpmb_u32 u32) {
+    size_t i;
+    uint32_t val;
+
+    val = 0;
+    for (i = 0; i < sizeof(u32.byte); i++)
+        val = val << 8 | u32.byte[i];
+
+    return val;
+}
diff --git a/trusty/utils/trusty-ut-ctrl/Android.bp b/trusty/utils/trusty-ut-ctrl/Android.bp
index 77d1f70..9c8af7b 100644
--- a/trusty/utils/trusty-ut-ctrl/Android.bp
+++ b/trusty/utils/trusty-ut-ctrl/Android.bp
@@ -20,6 +20,8 @@
     shared_libs: [
         "libc",
         "liblog",
+    ],
+    static_libs: [
         "libtrusty",
     ],
     gtest: false,
diff --git a/usbd/Android.bp b/usbd/Android.bp
index 3afa7a9..6a339a1 100644
--- a/usbd/Android.bp
+++ b/usbd/Android.bp
@@ -5,7 +5,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libhardware",